在 Swift 中将字典转换为 JSON
Posted
技术标签:
【中文标题】在 Swift 中将字典转换为 JSON【英文标题】:Convert Dictionary to JSON in Swift 【发布时间】:2015-04-14 10:34:08 【问题描述】:我已经创建了下一个字典:
var postJSON = [ids[0]:answersArray[0], ids[1]:answersArray[1], ids[2]:answersArray[2]] as Dictionary
我得到:
[2: B, 1: A, 3: C]
那么,如何将其转换为 JSON?
【问题讨论】:
NSJSONSerialization
【参考方案1】:
Swift 3.0
根据Swift API Design Guidelines,在 Swift 3 中,NSJSONSerialization
的名称及其方法已更改。
let dic = ["2": "B", "1": "A", "3": "C"]
do
let jsonData = try JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
// here "jsonData" is the dictionary encoded in JSON data
let decoded = try JSONSerialization.jsonObject(with: jsonData, options: [])
// here "decoded" is of type `Any`, decoded from JSON data
// you can now cast it with the right type
if let dictFromJSON = decoded as? [String:String]
// use dictFromJSON
catch
print(error.localizedDescription)
Swift 2.x
do
let jsonData = try NSJSONSerialization.dataWithJSONObject(dic, options: NSJSONWritingOptions.PrettyPrinted)
// here "jsonData" is the dictionary encoded in JSON data
let decoded = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
// here "decoded" is of type `AnyObject`, decoded from JSON data
// you can now cast it with the right type
if let dictFromJSON = decoded as? [String:String]
// use dictFromJSON
catch let error as NSError
print(error)
斯威夫特 1
var error: NSError?
if let jsonData = NSJSONSerialization.dataWithJSONObject(dic, options: NSJSONWritingOptions.PrettyPrinted, error: &error)
if error != nil
println(error)
else
// here "jsonData" is the dictionary encoded in JSON data
if let decoded = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as? [String:String]
if error != nil
println(error)
else
// here "decoded" is the dictionary decoded from JSON data
【讨论】:
我得到了下一个[2: A, 1: A, 3: A]
。但是大括号呢?
我不明白你的问题。什么大括号?你问过用 JSON 编码字典,这就是我的回答。
JSON 大括号,如"result":["body":"Question 3"]
@OrkhanAlizade 上述对dataWithJSONObject
的调用会生成“大括号”(即大括号)作为结果NSData
对象的一部分。
谢谢。旁注 - 考虑使用 d0 代替(字典)字典的缩写。【参考方案2】:
你的假设是错误的。仅仅因为调试器/Playground 在方括号中显示您的字典(这是 Cocoa 显示字典的方式),并不意味着 JSON 输出的格式就是这样。
以下是将字符串字典转换为 JSON 的示例代码:
Swift 3 版本:
import Foundation
let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
if let theJSONData = try? JSONSerialization.data(
withJSONObject: dictionary,
options: [])
let theJSONText = String(data: theJSONData,
encoding: .ascii)
print("JSON string = \(theJSONText!)")
要以“漂亮打印”格式显示上述内容,您需要将选项行更改为:
options: [.prettyPrinted]
或者在 Swift 2 语法中:
import Foundation
let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
let theJSONData = NSJSONSerialization.dataWithJSONObject(
dictionary ,
options: NSJSONWritingOptions(0),
error: nil)
let theJSONText = NSString(data: theJSONData!,
encoding: NSASCIIStringEncoding)
println("JSON string = \(theJSONText!)")
输出是
"JSON string = "anotherKey":"anotherValue","aKey":"aValue""
或以漂亮的格式:
"anotherKey" : "anotherValue",
"aKey" : "aValue"
正如您所期望的那样,字典在 JSON 输出中用大括号括起来。
编辑:
在 Swift 3/4 语法中,上面的代码如下所示:
let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
if let theJSONData = try? JSONSerialization.data(
withJSONObject: dictionary,
options: .prettyPrinted
),
let theJSONText = String(data: theJSONData,
encoding: String.Encoding.ascii)
print("JSON string = \n\(theJSONText)")
【讨论】:
一个普通的 Swift 字符串同样适用于 JSONText 声明。 @thefredelement,您如何将 NSData 直接转换为 Swift 字符串?数据到字符串的转换是 NSString 的一个函数。 我正在实现这个方法并在 Swift 字符串上使用了数据/编码初始化,我不确定它是否在 Swift 1.x 上可用。 拯救了我的一天。谢谢。 应该选择答案(y)【参考方案3】:斯威夫特 5:
let dic = ["2": "B", "1": "A", "3": "C"]
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(dic)
if let jsonString = String(data: jsonData, encoding: .utf8)
print(jsonString)
请注意,键和值必须实现 Codable
。字符串、整数和双精度(以及更多)已经是 Codable
。见Encoding and Decoding Custom Types。
另请注意:如评论中所述,Any
不符合Codable
。将您的数据调整为 Codable
可能仍然是一种好方法,以便您使用 Swift 类型(尤其是在您还要解码任何编码的 json 的情况下),这样您就可以更具声明性关于编码的结果。
【讨论】:
仅供参考,如果您的 dict 是 [String, Any] 类型,此解决方案将不起作用【参考方案4】:我对你的问题的回答如下
let dict = ["0": "ArrayObjectOne", "1": "ArrayObjecttwo", "2": "ArrayObjectThree"]
var error : NSError?
let jsonData = try! NSJSONSerialization.dataWithJSONObject(dict, options: NSJSONWritingOptions.PrettyPrinted)
let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String
print(jsonString)
答案是
"0" : "ArrayObjectOne",
"1" : "ArrayObjecttwo",
"2" : "ArrayObjectThree"
【讨论】:
【参考方案5】:Swift 4 Dictionary
扩展。
extension Dictionary
var jsonStringRepresentation: String?
guard let theJSONData = try? JSONSerialization.data(withJSONObject: self,
options: [.prettyPrinted]) else
return nil
return String(data: theJSONData, encoding: .ascii)
【讨论】:
这是解决问题的好方法和可重复使用的方法,但稍微解释一下会帮助新手更好地理解它。 如果字典的键包含自定义对象数组,这可以应用吗? 在公共扩展中使用encoding: .ascii
不是一个好主意。 .utf8
会更安全!
这个带有转义字符的打印有什么地方可以防止这种情况发生吗?【参考方案6】:
有时需要打印出服务器的响应以进行调试。这是我使用的一个函数:
extension Dictionary
var json: String
let invalidJson = "Not a valid JSON"
do
let jsonData = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
return String(bytes: jsonData, encoding: String.Encoding.utf8) ?? invalidJson
catch
return invalidJson
func printJson()
print(json)
使用示例:
(lldb) po dictionary.printJson()
"InviteId" : 2,
"EventId" : 13591,
"Messages" : [
"SenderUserId" : 9514,
"MessageText" : "test",
"RecipientUserId" : 9470
,
"SenderUserId" : 9514,
"MessageText" : "test",
"RecipientUserId" : 9470
],
"TargetUserId" : 9470,
"InvitedUsers" : [
9470
],
"InvitingUserId" : 9514,
"WillGo" : true,
"DateCreated" : "2016-08-24 14:01:08 +00:00"
【讨论】:
【参考方案7】:斯威夫特 5:
extension Dictionary
/// Convert Dictionary to JSON string
/// - Throws: exception if dictionary cannot be converted to JSON data or when data cannot be converted to UTF8 string
/// - Returns: JSON string
func toJson() throws -> String
let data = try JSONSerialization.data(withJSONObject: self)
if let string = String(data: data, encoding: .utf8)
return string
throw NSError(domain: "Dictionary", code: 1, userInfo: ["message": "Data cannot be converted to .utf8 string"])
【讨论】:
这适用于 Codable 类型,但要小心 String: Any,这会产生不正确的值!【参考方案8】:Swift 3:
let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: [])
let jsonString = String(data: jsonData!, encoding: .utf8)!
print(jsonString)
【讨论】:
如果任何部分为零,这将崩溃,强制展开结果是非常糟糕的做法。 // 无论如何,其他答案中已经有相同的信息(没有崩溃),请避免发布重复的内容。谢谢。【参考方案9】:您的问题的答案如下:
斯威夫特 2.1
do
if let postData : NSData = try NSJSONSerialization.dataWithJSONObject(dictDataToBeConverted, options: NSJSONWritingOptions.PrettyPrinted)
let json = NSString(data: postData, encoding: NSUTF8StringEncoding)! as String
print(json)
catch
print(error)
【讨论】:
【参考方案10】:在 Swift 5.4 中
extension Dictionary
var jsonData: Data?
return try? JSONSerialization.data(withJSONObject: self, options: [.prettyPrinted])
func toJSONString() -> String?
if let jsonData = jsonData
let jsonString = String(data: jsonData, encoding: .utf8)
return jsonString
return nil
将它作为变量的想法是因为你可以像这样重用它:
extension Dictionary
func decode<T:Codable>() throws -> T
return try JSONDecoder().decode(T.self, from: jsonData ?? Data())
【讨论】:
这适用于 Codable 类型,但要小心 String: Any,这会产生不正确的值! @Wo_0NDeR 哪个属性或方法会产生不正确的值?【参考方案11】:这是一个简单的扩展:
https://gist.github.com/stevenojo/0cb8afcba721838b8dcb115b846727c3
extension Dictionary
func jsonString() -> NSString?
let jsonData = try? JSONSerialization.data(withJSONObject: self, options: [])
guard jsonData != nil else return nil
let jsonString = String(data: jsonData!, encoding: .utf8)
guard jsonString != nil else return nil
return jsonString! as NSString
【讨论】:
【参考方案12】:使用lldb
(lldb) p JSONSerialization.data(withJSONObject: notification.request.content.userInfo, options: [])
(Data) $R16 = 375 bytes
(lldb) p String(data: $R16!, encoding: .utf8)!
(String) $R18 = "\"aps\": \"some_text\""
//or
p String(data: JSONSerialization.data(withJSONObject: notification.request.content.userInfo, options: [])!, encoding: .utf8)!
(String) $R4 = "\"aps\": \"some_text\""
【讨论】:
【参考方案13】:这对我有用:
import SwiftyJSON
extension JSON
mutating func appendIfKeyValuePair(key: String, value: Any)
if var dict = self.dictionaryObject
dict[key] = value
self = JSON(dict)
用法:
var data: JSON = []
data.appendIfKeyValuePair(key: "myKey", value: "myValue")
【讨论】:
【参考方案14】:private func convertDictToJson(dict : NSDictionary) -> NSDictionary?
var jsonDict : NSDictionary!
do
let jsonData = try JSONSerialization.data(withJSONObject:dict, options:[])
let jsonDataString = String(data: jsonData, encoding: String.Encoding.utf8)!
print("Post Request Params : \(jsonDataString)")
jsonDict = [ParameterKey : jsonDataString]
return jsonDict
catch
print("JSON serialization failed: \(error)")
jsonDict = nil
return jsonDict
【讨论】:
这里有几个错误。为什么使用 Foundation 的 NSDictionary 而不是 Swift 的 Dictionary?!另外,为什么要返回一个以字符串为值的新字典,而不是返回实际的 JSON 数据?这没有意义。此外,作为可选项返回的隐式展开的可选项也不是一个好主意。以上是关于在 Swift 中将字典转换为 JSON的主要内容,如果未能解决你的问题,请参考以下文章