Automatic JSON serialization and deserialization of objects in Swift

前端 未结 7 2017
走了就别回头了
走了就别回头了 2020-12-13 00:21

I\'m looking for a way to automatically serialize and deserialize class instances in Swift. Let\'s assume we have defined the following class …

class Person          


        
相关标签:
7条回答
  • 2020-12-13 00:34

    As indicated in WWDC2017 @ 24:48 (Swift 4), we will be able to use the Codable protocol. Example

    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.

    An alternative can be JSONCodable which is used by Swagger's code generator.

    0 讨论(0)
  • 2020-12-13 00:34

    You could use EVReflection for that. You can use code like:

    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)

    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

    0 讨论(0)
  • 2020-12-13 00:38

    With Swift 4, you simply have to make your class conform to Codable (Encodable and Decodable protocols) in order to be able to perform JSON serialization and deserialization.

    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 Person instance into a JSON string):

    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 Person instance):

    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"
     */
    
    0 讨论(0)
  • 2020-12-13 00:41

    First, create a Swift object like this

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

    After that, serialize your JSON data you retrieved, using the built-in NSJSONSerialization and parse the values into the Person object.

    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

    Swift-JsonSerialiser

    ROJSONParser

    0 讨论(0)
  • 2020-12-13 00:46

    There is a Foundation class called NSJSONSerialization which can do conversion to and from JSON.

    The method for converting from JSON to an object looks like this:

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

    Note that the first argument to this method is the JSON data, but not as a string object, instead as a NSData object (which is how you'll often times get JSON data anyway).

    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.

    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.


    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.

    0 讨论(0)
  • 2020-12-13 00:50

    You can achieve this by using ObjectMapper library. It'll give you more control on variable names and the values and the prepared JSON. After adding this library extend the Mappable class and define mapping(map: Map) function.

    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)
    
    0 讨论(0)
提交回复
热议问题