Home > Software engineering >  Custom JSON Decoder
Custom JSON Decoder

Time:01-15

Json:

let json = """
[{
    "name":"abc"
    "id":"abc123"
    "university":"CMU"
},
{
    "name":"xyz"
    "id":"xyz123"
    "university":"NYU"
}]
"""

Struct:

struct Student: Codable {
    let name: String
    let university: String
}

I know that I can do to get students list

let students = try JSONDecoder().decode([Student].self, from: json.data(using: .utf8)!)

But I am trying to create a dictionary so that I can access any student by student id.

let students = [String:Student]()
  1. How do I use codable for this problem?
  2. Is there a way I can use student id as the key and value as a student object?
  3. I know I can run a loop and append my dictionary, but I am looking for a better solution.

Thank you!

CodePudding user response:

you can use

step 1:

struct Student: Codable {
    var name: String = ""
    var id: String = ""
    var university: String = ""
}

step 2:

let students = try JSONDecoder().decode([Student].self, from: json.data(using: .utf8)!)

 let groupedDictionary = Dictionary(grouping: students, by: 
   {String($0.id)})

CodePudding user response:

You could decode the JSON as unkeyedContainer into a wrapper struct

let json = """
[{
    "name":"abc",
    "id":"abc123",
    "university":"CMU"
},
{
    "name":"xyz",
    "id":"xyz123",
    "university":"NYU"
}]
"""

struct Root : Decodable {
    var students = [String:Student]()
    
    init(from decoder: Decoder) throws {
        var arrayDecoder = try decoder.unkeyedContainer()
        while !arrayDecoder.isAtEnd {
            let student = try arrayDecoder.decode(Student.self)
            let id = student.id
            students[id] = student
        }
    }
}

struct Student: Decodable {
    let name, id, university: String
}

let result = try JSONDecoder().decode(Root.self, from: Data(json.utf8))
print(result.students)

CodePudding user response:

You can simply provide your own subscript for the collections where the Element is Student:


extension Collection where Element == Student {
    subscript(_ id: String) -> Element? {
        first(where: {$0.id == id})
    }
}

struct Student: Codable, Hashable {
    let name: String
    let id: String
    let university: String
}

let json = """
[{
    "name":"abc",
    "id":"abc123",
    "university":"CMU"
},
{
    "name":"xyz",
    "id":"xyz123",
    "university":"NYU"
}]
"""

let students = try JSONDecoder().decode([Student].self, from: Data(json.utf8))

if let student = students["xyz123"] {
    print(student.name)         // "xyz\n"
    print(student.id)           // "xyz123\n"
    print(student.university)   // "NYU\n"
}
  •  Tags:  
  • Related