Swift 4 - How to convert Json to swift Object automatically like Gson in java
Asked Answered
A

2

21

I am new in Swift 4 and trying to figure out How to convert Json to swift Object automatically like Gson in java. Is there is any plugin i can use which can convert my json to object and vice versa. I have tried to use SwiftyJson Library but couldnt understand what is syntax for directly converting the json to object mapper. In Gson conversion is as follow :

String jsonInString = gson.toJson(obj);
Staff staff = gson.fromJson(jsonInString, Staff.class);

Can you please suggest some really simple example for beginner like me . below is my swift person class :

class Person  {
    let firstName: String
    let lastName: String

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

below is method call to fetch response from server :

let response = Helper.makeHttpCall(url: "http://localhost:8080/HttpServices/GetBasicJson", method: "PUT", param: interestingNumbers)

In response variable I am getting json:

{
  "firstName": "John",
  "lastName": "doe"
}
Appealing answered 19/7, 2017 at 10:31 Comment(2)
Swift 4 introduces Codable protocol & JSONEncoder / JSONDecoder for this purpose. Here is a really comprehensive guide on this topic.Shawana
Yes, seems like Codable is a solution. However, it still requires typing unlike Gson!Jointer
B
29

There's no need for external libraries in Swift anymore. As of Swift 4, there are 2 protocols that can achieve what you are looking for: Decodable and Encodable which are grouped into the Codable typealias, as well as JSONDecoder.

You just need to create an entity that conforms to Codable (Decodable should be enough in this example).

struct Person: Codable {
    let firstName, lastName: String
}

// Assuming makeHttpCall has a callback:
Helper.makeHttpCall(url: "http://localhost:8080/HttpServices/GetBasicJson", method: "PUT", param: interestingNumbers, callback: { response in
    // response is a String ? Data ?
    // Assuming it's Data
    let person = try! decoder.decode(Person.self, for: response)

    // Uncomment if it's a String and comment the line before
    // let jsonData = response.data(encoding: .utf8)!
    // let person = try! decoder.decode(Person.self, for: jsonData)
    print(person)
})

More info:

Biochemistry answered 21/7, 2017 at 4:44 Comment(4)
Right, but when is a JSONArray what do you use?! You have wrap it in a "JSONObject"?Catalyze
No. You can use let persons = try! decoder.decode([Person.self], for: response)Biochemistry
What is decoder in this instance? As Decoder is a protocol it can be instantiated. Showing your declaration for decoder would be a big help.Avelinaaveline
@Avelinaaveline very late reply but since nobody answered and it might save a couple of minutes for others the decoder instance is actually let decoder = JSONDecoder(). SourcePisci
M
2

As @nathan Suggested

"There's no need for external libraries in Swift anymore."

But If you still want to go with the third party library like ObjectMapper

class Person : Mappable {
    var firstName: String?
    var lastName: String?
    required init?(map:Map) {

    }

   func mapping(map:Map){
      //assuming the first_name and last_name is what you have got in JSON
      // e.g in android you do like @SerializedName("first_name") to map
     firstName <- map["first_name"]
     lastName <- map["last_name"]
   }

}




let person = Mapper<Person>().map(JSONObject:response.result.value)

and extending the answer by @nathan to demonstrate @SerializedName annotation equivalent in iOS using Codable

struct Person : Codable {

        let firstName : String?
        let lastName : String?

        enum CodingKeys: String, CodingKey {
                case firstName = "first_name"
                case lastName = "last_name"
        }

}
Moiety answered 29/1, 2020 at 17:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.