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

时间:2014-11-08 18:43:17

标签: json serialization swift

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

class Person {
    let firstName: String
    let lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
}

...和Person实例:

let person = Person(firstName: "John", lastName: "Doe")

person的JSON表示如下:

{
    "firstName": "John",
    "lastName": "Doe"
}

现在,我的问题是:

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

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

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

7 个答案:

答案 0 :(得分:26)

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

public struct Person : Codable {
   public let firstName:String
   public let lastName:String
   public let location:Location
}

序列化

let payload: Data = try JSONEncoder().encode(person)

反序列化

let anotherPerson = try JSONDecoder().decode(Person.self, from: payload)

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

替代可以是JSONCodable代码生成器使用的Swagger's

答案 1 :(得分:20)

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

var person:Person = Person(json:jsonString)

var jsonString:String = person.toJsonString()

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

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

答案 2 :(得分:8)

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

import Foundation

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

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
}

用法#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"
 }
 */

用法#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"
 */

答案 3 :(得分:5)

有一个名为NSJSONSerialization的基础课程,可以与JSON进行转换。

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

let jsonObject = NSJSONSerialization.JSONObjectWithData(data, 
    options: NSJSONReadingOptions.MutableContainers, 
    error: &error) as NSDictionary

请注意,此方法的第一个参数是JSON数据,但不是作为字符串对象,而是作为NSData对象(这是您经常获取JSON数据的方式)

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

要反转此过程并从对象中创建JSON数据,您需要使用dataWithJSONObject,其中您将传递一个可转换为JSON且具有{{1}的对象}} 回。同样,您可能希望创建一个不需要参数作为类的实例方法的辅助方法。


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

答案 4 :(得分:4)

您可以使用ObjectMapper库来实现此目的。它将为您提供对变量名称,值以及准备好的JSON的更多控制权。添加此库后,扩展Mappable类并定义mapping(map: Map)函数。

例如

   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"]
       }

    }

使用如下

   let user = Mapper<User>().map(JSONString)

答案 5 :(得分:0)

首先,创建一个像这样的Swift对象

struct Person {
    var firstName: String?;
    var lastName: String?;
    init() {

    }
}

之后,使用内置的 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;
}

<强>更新

另请查看这些库

Swift-JsonSerialiser

ROJSONParser

答案 6 :(得分:0)

看看NSKeyValueCoding.h,特别是setValuesForKeysWithDictionary。将json反序列化为NSDictionary后,可以使用该字典实例创建和初始化对象,无需在对象上手动设置值。这将让您了解反序列化如何与json一起使用,但您很快就会发现需要对反序列化过程进行更多控制。这就是我在NSObject上实现一个类别的原因,它允许在json反序列化期间使用字典进行完全控制的NSObject初始化,它基本上比setValuesForKeysWithDictionary更能使对象更加丰富。我还有一个json反序列化器使用的协议,它允许反序列化的对象控制某些方面,例如,如果反序列化NSArray对象,它将询问该对象什么是存储在数组中的对象的类型名称。