Swift 中对象的自动 JSON 序列化和反序列化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26820720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Automatic JSON serialization and deserialization of objects in Swift
提问by Marius Schulz
I'm looking for a way to automatically serialize and deserialize class instances in Swift. Let's assume we have defined the following class …
我正在寻找一种在 Swift 中自动序列化和反序列化类实例的方法。假设我们已经定义了以下类……
class Person {
let firstName: String
let lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
}
… and Personinstance:
...和Person实例:
let person = Person(firstName: "John", lastName: "Doe")
The JSON representation of personwould be the following:
的 JSON 表示person如下:
{
"firstName": "John",
"lastName": "Doe"
}
Now, here are my questions:
现在,这是我的问题:
- How can I serialize the
personinstance and get the above JSON without having to manually add all properties of the class to a dictionary which gets turned into JSON? - How can I deserialize the above JSON and get back an instantiated object that is statically typed to be of type
Person? Again, I don't want to map the properties manually.
- 如何序列化
person实例并获取上述 JSON,而不必手动将类的所有属性添加到字典中,该字典会变成 JSON? - 如何反序列化上述 JSON 并取回静态类型为类型的实例化对象
Person?同样,我不想手动映射属性。
Here's how you'd do that in C# using Json.NET:
以下是使用Json.NET在 C# 中执行此操作的方法:
var person = new Person("John", "Doe");
string json = JsonConvert.SerializeObject(person);
// {"firstName":"John","lastName":"Doe"}
Person deserializedPerson = JsonConvert.DeserializeObject<Person>(json);
采纳答案by Alex Nolasco
As indicated in WWDC2017@ 24:48 (Swift 4), we will be able to use the Codable protocol. Example
如WWDC2017@ 24:48 ( Swift 4) 中所述,我们将能够使用 Codable 协议。例子
public struct Person : Codable {
public let firstName:String
public let lastName:String
public let location:Location
}
To serialize
序列化
let payload: Data = try JSONEncoder().encode(person)
To deserialize
反序列化
let anotherPerson = try JSONDecoder().decode(Person.self, from: payload)
Note that all properties must conform to the Codable protocol.
请注意,所有属性都必须符合 Codable 协议。
An alternativecan be JSONCodablewhich is used by Swagger'scode generator.
一个替代方案可以是JSONCodable其用于通过扬鞭的代码生成器。
回答by Edwin Vermeer
You could use EVReflectionfor that. You can use code like:
您可以为此使用EVReflection。您可以使用以下代码:
var person:Person = Person(json:jsonString)
or
或者
var jsonString:String = person.toJsonString()
See the GitHub page for more detailed sample code. You only have to make EVObject the base class of your data objects. No mapping is needed (as long as the json keys are the same as the property names)
有关更详细的示例代码,请参阅 GitHub 页面。你只需要让 EVObject 成为你的数据对象的基类。不需要映射(只要 json 键与属性名称相同)
Update:Swift 4 has support for Codable which makes it almost as easy as EVReflection but with better performance. If you do want to use an easy contractor like above, then you could use this extension: Stuff/Codable
更新:Swift 4 支持 Codable,这使得它几乎和 EVReflection 一样简单,但性能更好。如果您确实想使用像上面这样的简单承包商,那么您可以使用此扩展程序:Stuff/Codable
回答by Imanou Petit
With Swift 4, you simply have to make your class conform to Codable(Encodableand Decodableprotocols) in order to be able to perform JSON serialization and deserialization.
使用 Swift 4,您只需让您的类符合Codable(Encodable和Decodable协议),以便能够执行 JSON 序列化和反序列化。
import Foundation
class Person: Codable {
let firstName: String
let lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
}
Usage #1 (encode a Personinstance into a JSON string):
用法 #1(将Person实例编码为 JSON 字符串):
let person = Person(firstName: "John", lastName: "Doe")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted // if necessary
let data = try! encoder.encode(person)
let jsonString = String(data: data, encoding: .utf8)!
print(jsonString)
/*
prints:
{
"firstName" : "John",
"lastName" : "Doe"
}
*/
Usage #2 (decode a JSON string into a Personinstance):
用法 #2(将 JSON 字符串解码为Person实例):
let jsonString = """
{
"firstName" : "John",
"lastName" : "Doe"
}
"""
let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
let person = try! decoder.decode(Person.self, from: jsonData)
dump(person)
/*
prints:
? __lldb_expr_609.Person #0
- firstName: "John"
- lastName: "Doe"
*/
回答by nhgrif
There is a Foundation class called NSJSONSerializationwhich can do conversion to and from JSON.
有一个叫做 Foundation 的类NSJSONSerialization,它可以进行与JSON.
The method for converting from JSON to an object looks like this:
从 JSON 转换为对象的方法如下所示:
let jsonObject = NSJSONSerialization.JSONObjectWithData(data,
options: NSJSONReadingOptions.MutableContainers,
error: &error) as NSDictionary
Note that the first argument to this method is the JSONdata, but not as a string object, instead as a NSDataobject (which is how you'll often times get JSON data anyway).
请注意,此方法的第一个参数是JSON数据,但不是作为字符串对象,而是作为NSData对象(无论如何,这就是您经常获取 JSON 数据的方式)。
You most likely will want a factory method for your class that takes JSON data as an argument, makes use of this method and returns an initialize object of your class.
您很可能需要为您的类使用一个工厂方法,该方法将 JSON 数据作为参数,使用此方法并返回您的类的初始化对象。
To inverse this process and create JSON data out of an object, you'll want to make use of dataWithJSONObject, in which you'll pass an object that can be converted into JSON and have an NSData?returned. Again, you'll probably want to create a helper method that requires no arguments as an instance method of your class.
要反转此过程并从对象中创建 JSON 数据,您需要使用dataWithJSONObject,您将在其中传递一个可以转换为 JSON 并NSData?返回的对象。同样,您可能希望创建一个不需要参数的辅助方法作为类的实例方法。
As far as I know, the easiest way to handle this is to create a way to map your objects properties into a dictionary and pass that dictionary for turning your object into JSON data. Then when turning your JSON data into the object, expect a dictionary to be returned and reverse the mapping process. There may be an easier way though.
据我所知,处理这个问题的最简单方法是创建一种将对象属性映射到字典并传递该字典以将对象转换为 JSON 数据的方法。然后在将您的 JSON 数据转换为对象时,期望返回一个字典并反转映射过程。不过可能有更简单的方法。
回答by Penkey Suresh
You can achieve this by using ObjectMapperlibrary. It'll give you more control on variable names and the values and the prepared JSON. After adding this library extend the Mappableclass and define mapping(map: Map)function.
您可以通过使用ObjectMapper库来实现这一点。它将让您更好地控制变量名称和值以及准备好的 JSON。添加此库后,扩展Mappable类并定义mapping(map: Map)函数。
For example
例如
class User: Mappable {
var id: Int?
var name: String?
required init?(_ map: Map) {
}
// Mapping code
func mapping(map: Map) {
name <- map["name"]
id <- map["id"]
}
}
Use it like below
像下面一样使用它
let user = Mapper<User>().map(JSONString)
回答by Eddy Liu
First, create a Swift object like this
首先,像这样创建一个 Swift 对象
struct Person {
var firstName: String?;
var lastName: String?;
init() {
}
}
After that, serialize your JSON data you retrieved, using the built-in NSJSONSerializationand parse the values into the Personobject.
之后,使用内置的NSJSONSerialization序列化您检索到的 JSON 数据并将值解析为Person对象。
var person = Person();
var error: NSError?;
var response: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(), error: &error);
if let personDictionary = response as? NSDictionary {
person.firstName = personDictionary["firstName"] as? String;
person.lastName = personDictionary["lastName"] as? String;
}
UPDATE:
更新:
Also please take a look at those libraries
也请看看那些图书馆
回答by simplatek
Take a look at NSKeyValueCoding.h, specifically setValuesForKeysWithDictionary. Once you deserialize the json into a NSDictionary, you can then create and initialize your object with that dictionary instance, no need to manually set values on the object. This will give you an idea of how the deserialization could work with json, but you will soon find out you need more control over deserialization process. This is why I implement a category on NSObjectwhich allows fully controlled NSObjectinitialization with a dictionary during json deserialization, it basically enriches the object even further than setValuesForKeysWithDictionarycan do. I also have a protocol used by the json deserializer, which allows the object being deserialized to control certain aspects, for example, if deserializing an NSArray of objects, it will ask that object what is the type name of the objects stored in the array.
看看 NSKeyValueCoding.h,特别是setValuesForKeysWithDictionary. 一旦您将 json 反序列化为NSDictionary,您就可以使用该字典实例创建和初始化您的对象,而无需在对象上手动设置值。这将使您了解反序列化如何与 json 一起工作,但您很快就会发现您需要对反序列化过程进行更多控制。这就是为什么我实现了一个类别NSObject,允许NSObject在 json 反序列化期间使用字典完全控制初始化,它基本上比setValuesForKeysWithDictionary可以做。我还有一个 json 反序列化器使用的协议,它允许被反序列化的对象控制某些方面,例如,如果反序列化一个 NSArray 对象,它会询问该对象存储在数组中的对象的类型名称是什么。

