Realm + Swift, nested JSON - json

I have a problem since last 2 days. I can't get my JSON transformed to a Realm Object.
I have a json like below:
{
"gender" : "male",
"id" : "123456789",
"age_range" : {
"min" : 21
},
"last_name" : "LastName"
}
I have this Realm Models:
class UserObject: Object {
dynamic var userId: String = ""
dynamic var lastName: String?
dynamic var gender: String?
var ageRange = List<AgeRangeObject>()
required convenience init?(_ map: Map) {
self.init()
}
}
class AgeRangeObject: Object {
dynamic var min: Int = 0
}
And the way I am trying to create an instance of this model with ObjectMapper to parse json to dictionary and then create the model instance:
let userJSONModel = Mapper<User>().map(jsonString)
let realm = try! Realm()
do {
try realm.write {
let dict: [String : AnyObject] = [
"userId" : (userJSONModel?.userId)!,
"ageRange" : (userJSONModel?.ageRange)!,
"lastName" : (userJSONModel?.lastName)!,
"gender" : (userJSONModel?.gender)!
]
let userModel = UserObject(value: dict)
realm.add(userModel)
}
} catch {
print("Exception")
}
The problem occurs on this line: let userModel = UserObject(value: dict)
I get the folowing error:
*** Terminating app due to uncaught exception 'RLMException', reason: 'Invalid value 'min' to initialize object of type 'AgeRangeObject': missing key 'min''
I was looking on the stackoverflow:
Nested Arrays throwing error in realm.create(value: JSON) for Swift
How to convert Realm object to JSON with nested NSDate properties?
but my case is different.
Do you know what's the problem with that age range dictionary? Why it can't parse it well?
Thank you.

In your JSON, ageRange is a dictionary, whereas the UserObject.ageRange property is a List<AgeRangeObject>. You have mismatched models.
You either need to update your models to reflect the structure of your JSON:
var ageRange = List<AgeRangeObject>()
becomes
dynamic var ageRange: AgeRangeObject? = nil
or vice versa, update your JSON to reflect the structure of your models:
{
"gender" : "male",
"id" : "123456789",
"age_range" : [{
"min" : 21
}],
"last_name" : "LastName"
}

{
"key1" : "value1",
"key2" : "value2",
"array1" : [{
"key" : value
}],
"key3" : "value3"
}
For this you could use ObjectMapper's TransformType.
Reference: https://github.com/APUtils/ObjectMapperAdditions
My Code:
#objcMembers class RealmObject: Object, Mappable {
dynamic var listValues = List<MyRealmObject>()
required convenience init?(map: Map) {
self.init()
}
// Mappable
func mapping(map: Map) {
listValues <- (map["listValues"], RealmlistObjectTransform())
}
}
#objcMembers class MyRealmObject: Object, Mappable {
required convenience init?(map: Map) {
self.init()
}
// Mappable
func mapping(map: Map) {
}
}
class RealmlistObjectTransform: TransformType {
typealias Object = List<MyRealmObject> // My Realm Object here
typealias JSON = [[String: Any]] // Dictionary here
func transformFromJSON(_ value: Any?) -> List<MyRealmObject>? {
let list = List<MyRealmObject>()
if let actors = value as? [[String: Any]] {
let objects = Array<MyRealmObject>(JSONArray: actors)
list.append(objectsIn: objects)
}
return list
}
func transformToJSON(_ value: List<MyRealmObject>?) -> [[String: Any]]? {
if let actors = value?.sorted(byKeyPath: "").toArray(ofType: MyRealmObject.self).toJSON() {
return actors
}
return nil
}
}

Related

Append Nested Objects in Parameters of multi-form Swift using Alamofire

I am uploading multiple images as well as JSON data using "Content-type": "multipart/form-data"
my issue is, I have nested objects to pass to the parameters
I was looking for a solution, and what I find is nested data with an array of String or Int, not another custom object (I was struggling with it for so long)
struct Car: Codable{
var id :Int,
var name:String,
var address:String,
var new:Bool
var users:[User]
}
struct User: Codable{
var id :Int,
var name:String,
var address:String,
var age:Int
}
I wanted to convert the data to do a dictionary to use it as parameters
func addNewCae(newCar:Car, images:[UIImage]){
let encoder = JSONEncoder()
let jsonData = try! encoder.encode(newCar)
let test = convertStringToDictionary(text: jsonData)
print(test)
let headers: HTTPHeaders
headers = ["Content-type": "multipart/form-data",
"Content-Disposition" : "form-data"]
AF.upload(multipartFormData: { multipartFormData in
for imageData in images {
guard let imgData = imageData.pngData() else { return }
multipartFormData.append(imgData , withName: "images[]", fileName: "image.jpeg", mimeType: "image/jpeg")
}
for (key, value) in self.convertStringToDictionary(text: jsonData)! {
multipartFormData.append("\(value)".data(using: .utf8)!, withName: key)
}
},to: "\(url)", usingThreshold: UInt64.init(),
method: .post,
headers: headers).responseString{ response in
switch response.result {
case .success(let value):
print(value)
break
case .failure(let error):
print(error)
}
}
}
func convertStringToDictionary(data: Data) -> [String:AnyObject]? {
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject]
return json
} catch {
print("Something went wrong")
}
return nil
}
As a request of my code: all the car fields are registered in the database except the users' field
(in reality, I have more fields than that)
Why the users' field is not added to the parameters?
Any idea?
The users filed normally be of type [[String: AnyObject]] in the parameters
here is the data after I convert it to a dictionary
Optional(["name":"whatever" , "address": "here", "users": <__NSArrayM 0x6000008e4f90>(
{
"name" = "hello";
"address" = "there";
"age" = 20;
},
{
"name" = "hi";
"address" = "location";
"age" = 25;
}
)
, "new": 0])
hope am clear enough, I can add any further code or information if needed to be clearer
Thanks
Update
I did the encoding manually so now I have a correct dictionary format of type [String: AnyObject] but one of them is nested :
["name":"whatever" , "address": "here", "users": [
[
"name" = "hello";
"address" = "there";
"age" = 20;
],
[
"name" = "hi";
"address" = "location";
"age" = 25;
]
]
, "new": 0]
BUT, still, the "users" field is not able to be read, I think because the parameters don't support that kind of type?
Anyone have any other idea how to deal with these nested objects?

Return a value in a nested JSON array, using Alamofire and Swift

Super new to swift, JSON, and pretty all coding so I apologize in advance if this question is redundant to others on the site or I am missing something simple here.
I am looking to return the value of "text" ("1.7 mi") associated with "distance" in the "elements" array in the JSON code below:
{
"destination_addresses" : [ "30 Rockefeller Plaza, New York, NY 10112, USA" ],
"origin_addresses" : [ "352 7th Ave, New York, NY 10001, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "1.7 mi",
"value" : 2729
},
"duration" : {
"text" : "15 mins",
"value" : 887
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}
I retrieved the JSON data using Alamofire and the Google DistanceMatrix (see my code below), but am having trouble parsing the data to isolate what I need. I know the code below isn't close to what I need, but am unsure as to how to proceed.
func distanceMatrix(startLocation: String, endLocation: String) {
let myOrigin = startLocationTFText
let myDestination = destinationLocationTFText
let url = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=\(myOrigin)&destinations=\(myDestination)&key=API_Key
let encodedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
AF.request(encodedUrl!).responseJSON { response in
print(response.request as Any)
print(response.response as Any)
print(response.data as Any)
print(response.result as Any)
let json = JSON(response.data as Any)
Any help is much appreciated. Thank you.
You can use Decodable to get the desired result.
struct RootResponse: Decodable {
let destinationAddresses, originAddresses: [String]
let rows: [Rows]
let status: String
}
struct Rows: Decodable {
let elements: [Elements]
}
struct Elements: Decodable {
let distance, duration: Details
let status: String
}
struct Details: Decodable {
let text, value: String
}
This will be your model file and once you have added it then you can go back to your function and use it as:
func distanceMatrix(startLocation: String, endLocation: String) {
let myOrigin = startLocationTFText
let myDestination = destinationLocationTFText
let url = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=\(myOrigin)&destinations=\(myDestination)&key=API_Key"
let encodedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
AF.request(encodedUrl!).responseJSON { response in
print(response.request as Any)
print(response.response as Any)
print(response.data as Any)
print(response.result as Any)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
guard let json = try? decoder.decode(RootResponse.self, from: response.data) else { print("Unable to parse JSON"); return }
print(json)
print(json.rows.first?.elements.first?.distance.value) // This is how you can get the value, but it will be better to safely unwrap them and I have also used first? to get the first object but this is an array and you can always use a for loop for further purpose
}

Swift 4 Decoding to different models from custom JSON objects

I have a websocket which generate different json objects. Objects could contain no any common fields
{
"type": "apple",
"kind": "fruit",
"eatable": true
}
{
"item": "key",
"active": true
}
{
"tool": "screwdriver",
"original": "toolBox",
"cross-head": true
}
I have a list of classes for them (they could contain some logic) so I need to parse it to map some those models with some hierarchical structure e.g.
Try to parse fruits if they fails try to parse keys if they fails try to parse toolbox. Sometimes I need to add some new classes to parse some objects and some new fields to existing classes.
How to organize picking class for parsing?
Update
I have no control on backend data so I cannot add any fields to JSON I have.
Objects come one at a time. I have separate class models for most of them. The issue is to choose the right class to map the JSON fields.
You can do it this way:
First you declare your types conforming to the Decodable protocole:
struct Fruit : Decodable {
let type : String
let kind : String
let eatable : Bool
}
struct Tool : Decodable {
let tool : String
let original : String
let crossHead : Bool
enum CodingKeys: String, CodingKey {
case tool = "tool"
case original = "original"
case crossHead = "cross-head"
}
}
Then you extend Decodable to "reverse" the use of the genericity:
extension Decodable {
static func decode(data : Data, decoder : JSONDecoder = JSONDecoder()) -> Self? {
return try? decoder.decode(Self.self, from: data)
}
}
You then extend JSONDecoder to try decodable types among the ones you want to test:
extension JSONDecoder {
func decode(possibleTypes : [Decodable.Type], from data: Data) -> Any? {
for type in possibleTypes {
if let value = type.decode(data: data, decoder: self) {
return value
}
}
return nil
}
}
And eventually you specify the types you want to try and decode:
let decodableTypes : [Decodable.Type] = [Fruit.self, Tool.self]
You can then use it to decode your JSON:
let jsonString = """
{
"tool": "screwdriver",
"original": "toolBox",
"cross-head": true
}
"""
let jsonData = jsonString.data(using: .utf8)!
let myUnknownObject = JSONDecoder().decode(possibleTypes: decodableTypes, from: jsonData)
And voilà!!!
Now you can add as much types as you want in your decodableTypes as long as they conform to the Decodable protocol.
It is not the best approach, because if you have many types it won't be optimal, but this way you don't need to add a discriminating field in your data.
Try finding the key you are looking for that model class if that key is not present in that object try another model class. This should make you determine which model class is suitable for the given object.
Use the unique key which is not present in any other model class
Example:
var array = NSArray(array: [[
"type": "apple",
"kind": "fruit",
"eatable": true
],
[
"item": "key",
"active": true
],
[
"tool": "screwdriver",
"original": "toolBox",
"cross-head": true
]])
for model in array as! [NSDictionary]
{
if(model.value(forKey: "type") != nil)
{
print("use Fruit Model Class")
}
else if(model.value(forKey: "item") != nil)
{
print("use second model class")
}
else
{
print("use third model class")
}
}
If all those fields are related or a union style, you may consider user Enum, which is also very easy to implement.
let data1 = """
[{
"type": "apple",
"kind": "fruit",
"eatable": true
},
{
"item": "key",
"active": true
},
{
"tool": "screwdriver",
"original": "toolBox",
"cross-head": true
}]
""".data(using: .utf8)!
struct JSONType : Decodable{
let type: String
let kind: String
let eatable : Bool
}
struct JSONItem : Decodable{
let item: String
let active : Bool
}
struct JSONTool : Decodable{
let tool: String
let original : String
let crosshead : Bool
enum CodingKeys: String, CodingKey {
case tool = "tool"
case original = "original"
case crosshead = "cross-head"
}
}
enum JSONData : Decodable{
case type(JSONType)
case item(JSONItem)
case tool(JSONTool)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do{ let temp = try container.decode(JSONType.self); self = .type(temp) ; return}
catch{do { let temp = try container.decode(JSONItem.self) ; self = .item(temp) ; return}
catch{ let temp = try container.decode(JSONTool.self) ; self = .tool(temp) ; return}}
try self.init(from: decoder)
}
func getValue()-> Any{
switch self {
case let .type(x): return x
case let .item(x): return x
case let .tool(x): return x
}
}
}
let result = try JSONDecoder().decode([JSONData].self, from: data1)
print(result[0].getValue())
print (result[1].getValue())
print (result[2].getValue())

From Swift object to json (formated [String: Any]) for alamofire REST post parameter (defined as [String: Any])

My purpose is to execute a REST post request via Alamofire.
I have an object:
struct Dog: Codable {
var name: String
var owner: String
}
I use this :
let JSONString = user.toJSONString(prettyPrint: true) //ObjectMapper call
returning :
{
"name" : "Jon",
"owner" : "Jon Doe"
}
But I want a [String: Any] structure, suitable for alamofire request like :
[
"name" : "Jon",
"owner" : "Jon Doe"
]
How to do that ?
Your Dog is not correctly configured to use ObjectMapper, missing Mappable protocol.
struct Dog: Mappable {
var name: String?
var owner: String?
init?(map: Map) {
}
// Mappable
mutating func mapping(map: Map) {
name <- map["name"]
owner <- map["owner"]
}
}
Then you can use BaseMappable.toJSON to pass to Alamofire's parameter, which is [String: Any]
let parameters: Parameters = user.toJSON()
_ = Alamofire.request(theURL, method:.post, parameters: parameters, encoding: JSONEncoding.default).validate().responseJSON() {
// -----...
}
PS:
Your user mustn't be a Dog I guess? :P
One solution is to add a property to your struct to return a dictionary representation, either complicated
var dictionaryRepresentation : [String : String] {
return try! JSONSerialization.jsonObject(with: try! JSONEncoder().encode(self)) as! [String : String]
}
or very simple
var dictionaryRepresentation : [String : String] {
return ["name" : name, "owner" : owner]
}
Note:
Basically never send prettyPrinted strings to a server. It doesn't care at all about prettiness.

Deserialize JSON / NSDictionary to Swift objects

Is there a way to properly deserialize a JSON response to Swift objects resp. using DTOs as containers for fixed JSON APIs?
Something similar to http://james.newtonking.com/json or something like this example from Java
User user = jsonResponse.readEntity(User.class);
whereby jsonResponse.toString() is something like
{
"name": "myUser",
"email": "user#example.com",
"password": "passwordHash"
}
SWIFT 4 Update
Since you give a very simple JSON object the code prepared for to handle that model. If you need more complicated JSON models you need to improve this sample.
Your Custom Object
class Person : NSObject {
var name : String = ""
var email : String = ""
var password : String = ""
init(JSONString: String) {
super.init()
var error : NSError?
let JSONData = JSONString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let JSONDictionary: Dictionary = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &error) as NSDictionary
// Loop
for (key, value) in JSONDictionary {
let keyName = key as String
let keyValue: String = value as String
// If property exists
if (self.respondsToSelector(NSSelectorFromString(keyName))) {
self.setValue(keyValue, forKey: keyName)
}
}
// Or you can do it with using
// self.setValuesForKeysWithDictionary(JSONDictionary)
// instead of loop method above
}
}
And this is how you invoke your custom class with JSON string.
override func viewDidLoad() {
super.viewDidLoad()
let jsonString = "{ \"name\":\"myUser\", \"email\":\"user#example.com\", \"password\":\"passwordHash\" }"
var aPerson : Person = Person(JSONString: jsonString)
println(aPerson.name) // Output is "myUser"
}
I recommend that you use code generation (http://www.json4swift.com) to create native models out of the json response, this will save your time of parsing by hand and reduce the risk of errors due to mistaken keys, all elements will be accessible by model properties, this will be purely native and the models will make more sense rather checking the keys.
Your conversion will be as simple as:
let userObject = UserClass(userDictionary)
print(userObject!.name)
Swift 2: I really like the previous post of Mohacs! To make it more object oriented, i wrote a matching Extension:
extension NSObject{
convenience init(jsonStr:String) {
self.init()
if let jsonData = jsonStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
{
do {
let json = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! [String: AnyObject]
// Loop
for (key, value) in json {
let keyName = key as String
let keyValue: String = value as! String
// If property exists
if (self.respondsToSelector(NSSelectorFromString(keyName))) {
self.setValue(keyValue, forKey: keyName)
}
}
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
}
else
{
print("json is of wrong format!")
}
}
}
custom classes:
class Person : NSObject {
var name : String?
var email : String?
var password : String?
}
class Address : NSObject {
var city : String?
var zip : String?
}
invoking custom classes with JSON string:
var jsonString = "{ \"name\":\"myUser\", \"email\":\"user#example.com\", \"password\":\"passwordHash\" }"
let aPerson = Person(jsonStr: jsonString)
print(aPerson.name!) // Output is "myUser"
jsonString = "{ \"city\":\"Berlin\", \"zip\":\"12345\" }"
let aAddress = Address(jsonStr: jsonString)
print(aAddress.city!) // Output is "Berlin"
Yet another JSON handler I wrote:
https://github.com/dankogai/swift-json
With it you can go like this:
let obj:[String:AnyObject] = [
"array": [JSON.null, false, 0, "", [], [:]],
"object":[
"null": JSON.null,
"bool": true,
"int": 42,
"double": 3.141592653589793,
"string": "a α\t弾\n𪚲",
"array": [],
"object": [:]
],
"url":"http://blog.livedoor.com/dankogai/"
]
let json = JSON(obj)
json.toString()
json["object"]["null"].asNull // NSNull()
json["object"]["bool"].asBool // true
json["object"]["int"].asInt // 42
json["object"]["double"].asDouble // 3.141592653589793
json["object"]["string"].asString // "a α\t弾\n𪚲"
json["array"][0].asNull // NSNull()
json["array"][1].asBool // false
json["array"][2].asInt // 0
json["array"][3].asString // ""
As you see no !? needed between subscripts.
In addition to that you can apply your own schema like this:
//// schema by subclassing
class MyJSON : JSON {
override init(_ obj:AnyObject){ super.init(obj) }
override init(_ json:JSON) { super.init(json) }
var null :NSNull? { return self["null"].asNull }
var bool :Bool? { return self["bool"].asBool }
var int :Int? { return self["int"].asInt }
var double:Double? { return self["double"].asDouble }
var string:String? { return self["string"].asString }
var url: String? { return self["url"].asString }
var array :MyJSON { return MyJSON(self["array"]) }
var object:MyJSON { return MyJSON(self["object"]) }
}
let myjson = MyJSON(obj)
myjson.object.null // NSNull?
myjson.object.bool // Bool?
myjson.object.int // Int?
myjson.object.double // Double?
myjson.object.string // String?
myjson.url // String?
There's a great example by Apple for deserializing JSON with Swift 2.0
The trick is to use the guard keyword and chain the assignments like so:
init?(attributes: [String : AnyObject]) {
guard let name = attributes["name"] as? String,
let coordinates = attributes["coordinates"] as? [String: Double],
let latitude = coordinates["lat"],
let longitude = coordinates["lng"],
else {
return nil
}
self.name = name
self.coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
I personally prefer native parsing vs any 3rd party, as it is transparent and magic-less. (and bug less?)
Using quicktype, I generated your model and serialization helpers from your sample:
import Foundation
struct User: Codable {
let name: String
let email: String
let password: String
}
extension User {
static func from(json: String, using encoding: String.Encoding = .utf8) -> OtherUser? {
guard let data = json.data(using: encoding) else { return nil }
return OtherUser.from(data: data)
}
static func from(data: Data) -> OtherUser? {
let decoder = JSONDecoder()
return try? decoder.decode(OtherUser.self, from: data)
}
var jsonData: Data? {
let encoder = JSONEncoder()
return try? encoder.encode(self)
}
var jsonString: String? {
guard let data = self.jsonData else { return nil }
return String(data: data, encoding: .utf8)
}
}
Then parse User values like this:
let user = User.from(json: """{
"name": "myUser",
"email": "user#example.com",
"password": "passwordHash"
}""")!
I wrote this small open-source library recently that lets you quickly and easily deserialize dictionaries into Swift objects: https://github.com/isair/JSONHelper
Using it, deserializing data becomes as easy as this:
var myInstance = MyClass(data: jsonDictionary)
or
myInstance <-- jsonDictionary
And models need to look only like this:
struct SomeObjectType: Deserializable {
var someProperty: Int?
var someOtherProperty: AnotherObjectType?
var yetAnotherProperty: [YetAnotherObjectType]?
init(data: [String: AnyObject]) {
someProperty <-- data["some_key"]
someOtherProperty <-- data["some_other_key"]
yetAnotherProperty <-- data["yet_another_key"]
}
}
Which, in your case, would be:
struct Person: Deserializable {
var name: String?
var email: String?
var password: String?
init(data: [String: AnyObject]) {
name <-- data["name"]
email <-- data["email"]
password <-- data["password"]
}
}
If you would like parse from and to json without the need to manually map keys and fields, then you could also use EVReflection. You can then use code like:
var user:User = User(json:jsonString)
or
var jsonString:String = user.toJsonString()
The only thing you need to do is to use EVObject as your data objects base class.
See the GitHub page for more detailed sample code
I am expanding upon Mohacs and Peter Kreinz's excellent answers just a bit to cover the array of like objects case where each object contains a mixture of valid JSON data types. If the JSON data one is parsing is an array of like objects containing a mixture of JSON data types, the do loop for parsing the JSON data becomes this.
// Array of parsed objects
var parsedObjects = [ParsedObject]()
do {
let json = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as [Dictionary<String, AnyObject>]
// Loop through objects
for dict in json {
// ParsedObject is a single instance of an object inside the JSON data
// Its properties are a mixture of String, Int, Double and Bool
let parsedObject = ParsedObject()
// Loop through key/values in object parsed from JSON
for (key, value) in json {
// If property exists, set the value
if (parsedObject.respondsToSelector(NSSelectorFromString(keyName))) {
// setValue can handle AnyObject when assigning property value
parsedObject.setValue(keyValue, forKey: keyName)
}
}
parsedObjects.append(parsedObject)
}
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
This way lets you get the user from a URL. It's parse the NSData to a NSDictionary and then to your NSObject.
let urlS = "http://api.localhost:3000/"
func getUser(username: Strung) -> User {
var user = User()
let url = NSURL(string: "\(urlS)\(username)")
if let data = NSData(contentsOfURL: url!) {
setKeysAndValues(user, dictionary: parseData(data))
}
return user
}
func setKeysAndValues (object : AnyObject, dictionary : NSDictionary) -> AnyObject {
for (key, value) in dictionary {
if let key = key as? String, let value = value as? String {
if (object.respondsToSelector(NSSelectorFromString(key))) {
object.setValue(value, forKey: key)
}
}
}
return object
}
func parseData (data : NSData) -> NSDictionary {
var error: NSError?
return NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as! NSDictionary
}
In Swift 4, You can use the Decoding, CodingKey protocols to deserialize the JSON response:
Create the class which confirm the decodable protocol
class UserInfo: Decodable
Create members of the class
var name: String
var email: String
var password: String
Create JSON key enum which inherits from CodingKey
enum UserInfoCodingKey: String, CodingKey {
case name
case password
case emailId
}
Implement init
required init(from decoder: Decoder) throws
The whole class look like :
Call Decoder
// jsonData is JSON response and we get the userInfo object
let userInfo = try JsonDecoder().decode(UserInfo.self, from: jsonData)
You do this by using NSJSONSerialization. Where data is your JSON.
First wrap it in an if statement to provide some error handling capablity
if let data = data,
json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: AnyObject] {
// Do stuff
} else {
// Do stuff
print("No Data :/")
}
then assign them:
let email = json["email"] as? String
let name = json["name"] as? String
let password = json["password"] as? String
Now, This will show you the result:
print("Found User iname: \(name) with email: \(email) and pass \(password)")
Taken from this Swift Parse JSON tutorial. You should check out the tutorial as it goes a lot more in depth and covers better error handling.