Home > other >  How to create a model in Swift from different data-type Json array?
How to create a model in Swift from different data-type Json array?

Time:09-29

I'm trying to create a Codable Struct in Swift based on the JSON I'm receiving.

The Json I have is:

{
        "data": [
        {
            "id": "a123b321c456xyz",
            "timeUsed": 12345678,
            "input": [
                [
                    "address_1a123b321c456xyz",
                    {
                        "getSomeString": "0123456789",
                        "getSomeObjectArray": []
                    }
                ],
                [
                    "address_2a123b321c456xyz",
                    {
                        "getSomeString": "0123456789",
                        "getSomeObjectArray": []
                    }
                ]
            ],
            "output": [
                [
                    "address_3a123b321c456xyz",
                    {
                        "getSomeString": "0123456789",
                        "getSomeObjectArray": []
                    }
                ],
                [
                    "address_4a123b321c456xyz",
                    {
                        "getSomeString": "0123456789",
                        "getSomeObjectArray": []
                    }
                ]
            ],
            "getSomeData": {
                "getSomeString": "0123456789",
                "getSomeObjectArray": []
            }
        }
    ]
}

The Models that I tried to use

struct RequestData: Codable {
    let data: [RequestMyData]
}

struct RequestMyData: Codable {
    let id: String
    let timeUsed: Int
    let input: [MixedData]
    let output: [MixedData]
    let getSomeData: GetSomeData
}

struct MixedData: Codable {
    //What should I do here?
}

struct GetSomeData: Codable {
    let getSomeString: String
    let getSomeObjectArray: [Object]
}

So, what confuses me is this part of JSON:

[
     "address_1a123b321c456xyz",
     {
         "getSomeString": "0123456789",
         "getSomeObjectArray": []
     }
],

If you need additional explanation, please comment below. Thank you in advance.

CodePudding user response:

That is some truly strange json but it can be decoded :)

First change MixedData to

struct MixedData: Codable {
    let addressField: String
    let someData: GetSomeData
}

and then add a custom init(from:) to RequestMyData where we use an unkeyed container for the input and output arrays and when looping those arrays we create another unkeyed container to decode to the MixedData type

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    id = try container.decode(String.self, forKey: .id)
    timeUsed = try container.decode(Int.self, forKey: .timeUsed)
    
    input = try Self.decodeMixedData(try container.nestedUnkeyedContainer(forKey: .input))
    output = try Self.decodeMixedData(try container.nestedUnkeyedContainer(forKey: .output))

    getSomeData = try container.decode(GetSomeData.self, forKey: .getSomeData)
}

private static func decodeMixedData(_ unkeyedContainer: UnkeyedDecodingContainer) throws -> [MixedData] {
    var container = unkeyedContainer
    var result = [MixedData]()
    while !container.isAtEnd {
        var innerContainer = try container.nestedUnkeyedContainer()
        let mixed = MixedData(addressField: try innerContainer.decode(String.self),
                              someData: try innerContainer.decode(GetSomeData.self))
        result.append(mixed)
    }

    return result
}

Note that the property getSomeData is not an array.

  • Related