utahiosmac / Marshal

Marshaling the typeless wild west of [String: Any]
MIT License
698 stars 63 forks source link

Difficulties parsing JSON Objects #109

Open giacmarangoni opened 7 years ago

giacmarangoni commented 7 years ago

Hi guys, I really want to thank you for you awesome work, I think Marshal is the fastest and lightweight library to deal with JSON structures. I'm facing a problem parsing a simple data structures:

"students": {
     "mrngcm":{
         "first_name":"John",
         "last_name":"Doe",
         "courses": {
             "MAT": 28
         }
     }
     ...
}

Here my model class:

import Foundation
import Marshal

class Student: Unmarshaling {
    var id: String
    var firstName: String
    var lastName: String
    var courses: [String:Int]

    required init(object: MarshaledObject) throws {
        self.firstName = try object.value(for: "first_name")
        self.lastName = try object.value(for: "last_name")
        self.courses = try object.value(for: "courses")
    }
}
let json: MarshalDictionary = try! JSONSerialization.jsonObject(with: dataFromString, options: []) as! MarshalDictionary
let students: [String: Student] = try! json.value(for: "students")

I don't exactly how to assign key to model id and additionally I'm getting and error while extracting courses dictionary: fatal error: try!' expression unexpectedly raised an error: Type mismatch. Expected type Dictionary<String, Int> for key: courses. Got '__NSArray0

Do you have any suggestion? Thank you so much

jarsen commented 7 years ago

I'm not really sure where Marshal thinks you're getting an array from given your example. But that's what it seems to think.

As to the first part of the question, that's tricky. Marshal isn't designed around this use case. My best suggestion would be to not use any of Marshal's built in helpers for converting collections, and instead do your own for map over the key value pairs of your dictionary. Then, inside the loop, init a a new student object using the dictionary's value, and then set the id to the key.

jarsen commented 7 years ago

in other words, something maybe like

let students = json.map { key, value in
    var student = try Student(object: value)
    student.id = key
    return student
}
giacmarangoni commented 7 years ago

Thank you for your help. It works.