-2.9 C
New York
Saturday, December 14, 2024

ios – Parsing JSON in Swift Error: Anticipated to decode Array however discovered a dictionary as an alternative


The documentation of OrderedCollection describes which construction is anticipated for this kind:

OrderedDictionary expects its contents to be encoded as alternating key-value pairs in an unkeyed container.

I.e. if you wish to use OrderedCollection, you need to use a special JSON construction:

[
    {
        "day": "Monday",
        "locationName": "Memorial Union Quad",
        "coordinate": [38.54141, -121.74845],
        "menu": [
            "Penne Pasta w/ Bolognese",
            ["🌾","🐷"],
            "Penne Pasta w/ Roasted Mushrooms",
            ["🌾","V"]
        ]
    }
]    

Typically, you shouldn’t use a JSON object however an array for menu if the order of the gadgets is vital. In accordance with the JSON specification, the order of the properties of an object mustn’t matter.

If you cannot management how the JSON will get structured:

Notice that, as described above, there may be the issue that the order of the JSON object properties mustn’t matter.
So the next resolution just isn’t beneficial if the order issues!

You possibly can decode the JSON you have got posted with the next object construction:

struct Menu: Hashable {
    var id: UUID = { UUID() }

    let day: String
    let locationName: String
    let coordinate: [Double]
    let menu: [String: [String]]
}

If in case you have management over the JSON construction:

There are a number of methods to construction or decode the info otherwise. Right here is one different:

struct Menu: Codable, Hashable {
    var id: UUID { UUID() }

    let day: String
    let locationName: String
    let coordinate: [Double]
    let menu: [MenuItem]
}

struct MenuItem: Codable, Hashable {
    let description: String
    let components: [String]
}

With the JSON having the next construction:

[
    {
        "day": "Monday",
        "locationName": "Memorial Union Quad",
        "coordinate": [38.54141, -121.74845],
        "menu": [
            {
                "description": "Penne Pasta w/ Bolognese",
                "ingredients": ["🌾","🐷"]
            },
            {
                "description": "Penne Pasta w/ Roasted Mushrooms",
                "components": ["🌾","V"]
            }
        ]
    }
]

Testing your code:

I usually suggest writing a unit check for one of these downside / code, as that is the simplest solution to check the performance:

import Testing

struct MenuTests {
    @Check
    func testDecodingSucceedsAndReturnsProperData() async throws {
        let decoder = JSONDecoder()
        let menus = attempt decoder.decode([Menu].self, from: Self.jsonData)

        let menu = attempt #require(menus.first)
        #count on(menu.day == "Monday")
        #count on(menu.locationName == "Memorial Union Quad")
        #count on(menu.coordinate == [38.54141, -121.74845])

        #count on(menu.menu == [
            MenuItem(description: "Penne Pasta w/ Bolognese", ingredients: ["🌾","🐷"]),
            MenuItem(description: "Penne Pasta w/ Roasted Mushrooms", components: ["🌾","V"]),
        ])
    }
}

non-public extension MenuTests {
    static let jsonData = """
    [
        {
            "day": "Monday",
            "locationName": "Memorial Union Quad",
            "coordinate": [38.54141, -121.74845],
            "menu": [
                {
                    "description": "Penne Pasta w/ Bolognese",
                    "ingredients": ["🌾","🐷"]
                },
                {
                    "description": "Penne Pasta w/ Roasted Mushrooms",
                    "components": ["🌾","V"]
                }
            ]
        }
    ]    
    """.knowledge(utilizing: .utf8)!
}

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles