Swift中对象的自动JSON序列化和反序列化

Mar*_*ulz 39 serialization json swift

我正在寻找一种方法来自动序列化和反序列化Swift中的类实例.我们假设我们定义了以下类......

class Person {
    let firstName: String
    let lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
}
Run Code Online (Sandbox Code Playgroud)

......和Person实例:

let person = Person(firstName: "John", lastName: "Doe")
Run Code Online (Sandbox Code Playgroud)

JSON表示person将如下:

{
    "firstName": "John",
    "lastName": "Doe"
}
Run Code Online (Sandbox Code Playgroud)

现在,这是我的问题:

  1. 如何序列化person实例并获取上述JSON,而无需手动将类的所有属性添加到转换为JSON的字典中?
  2. 如何反序列化上面的JSON并获取一个静态类型为类型的实例化对象Person?同样,我不想手动映射属性.

以下是使用Json.NET在C#中执行此操作的方法:

var person = new Person("John", "Doe");
string json = JsonConvert.SerializeObject(person);
// {"firstName":"John","lastName":"Doe"}

Person deserializedPerson = JsonConvert.DeserializeObject<Person>(json);
Run Code Online (Sandbox Code Playgroud)

Ale*_*sco 26

WWDC2017 @ 24:48(Swift 4)所示,我们将能够使用Codable协议.例

public struct Person : Codable {
   public let firstName:String
   public let lastName:String
   public let location:Location
}
Run Code Online (Sandbox Code Playgroud)

要序列化

let payload: Data = try JSONEncoder().encode(person)
Run Code Online (Sandbox Code Playgroud)

反序列化

let anotherPerson = try JSONDecoder().decode(Person.self, from: payload)
Run Code Online (Sandbox Code Playgroud)

请注意,所有属性都必须符合Codable协议.

一个替代方案可以是JSONCodable其用于通过扬鞭的代码生成器.


Edw*_*eer 20

您可以使用EVReflection.您可以使用以下代码:

var person:Person = Person(json:jsonString)
Run Code Online (Sandbox Code Playgroud)

要么

var jsonString:String = person.toJsonString()
Run Code Online (Sandbox Code Playgroud)

有关更详细的示例代码,请参阅GitHub页面.您只需将EVObject作为数据对象的基类.不需要映射(只要json键与属性名称相同)

更新: Swift 4支持Codable,这使得它几乎像EVReflection一样简单,但具有更好的性能.如果您确实想使用上面的简单承包商,那么您可以使用此扩展名:Stuff/Codable


Ima*_*tit 8

使用Swift 4,您只需使您的类符合Codable(EncodableDecodable协议),以便能够执行JSON序列化和反序列化.

import Foundation

class Person: Codable {
    let firstName: String
    let lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
}
Run Code Online (Sandbox Code Playgroud)

用法#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"
 }
 */
Run Code Online (Sandbox Code Playgroud)

用法#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"
 */
Run Code Online (Sandbox Code Playgroud)


nhg*_*rif 5

有一个叫做基础类NSJSONSerialization,它可以进行转换JSON.

从JSON转换为对象的方法如下所示:

let jsonObject = NSJSONSerialization.JSONObjectWithData(data, 
    options: NSJSONReadingOptions.MutableContainers, 
    error: &error) as NSDictionary
Run Code Online (Sandbox Code Playgroud)

请注意,此方法的第一个参数是JSON数据,但不是作为字符串对象,而是作为NSData对象(无论如何,您经常会获得JSON数据).

您很可能需要一个以JSON数据作为参数的类的工厂方法,使用此方法并返回类的初始化对象.

要反转此过程并从对象创建JSON数据,您将需要使用dataWithJSONObject,您将传递一个可以转换为JSON并NSData?返回的对象.同样,您可能希望创建一个不需要参数作为类的实例方法的辅助方法.


据我所知,处理此问题的最简单方法是创建一种方法将对象属性映射到字典中,并传递该字典以将对象转换为JSON数据.然后,当您将JSON数据转换为对象时,期望返回字典并反转映射过程.可能有一种更简单的方法.

  • 我知道`NSJSONSerialization` 和使用字典,但这不是我正在寻找的特别* 不是*。手动完成所有这些工作是编写样板代码的一种容易出错的方式,我在这里试图避免这种方式。 (2认同)
  • 您可以使用`NSCoding`但它仍然需要一些样板代码.请参阅:http://nshipster.com/nscoding/ (2认同)