简体   繁体   中英

Decoding JSON that has a dynamic key value with the key value name found elsewhere in JSON model using Swift Decodable

When I make an API request, I get returned a JSON structure that contains several objects which all have unique key value names. Therefore I cannot use the regular Decodable protocol to break down the JSON into different instances. However, these key value names are found elsewhere in my JSON structure under known constant values that I can access normally. Here is some example code I created to demonstrate my issue:

let jsonString = """
{
    "uniqueObjects": {
        "uniqueObject:1132435": {
            "firstName": "John"
            "lastName": "Smith"
        }
        "uniqueObject2:119672": {
            "firstName": "Jane"
            "lastName": "Doe"
        }
        "uniqueObject3:008997": {
            "firstName": "Sam"
            "lastName": "Greenfield"
        }
    }
    "keys": {
        "object1": {
            "key": "uniqueObject1:132435"
        }
        "object2": {
            "key": "uniqueObject2:119672"
        }
        "object3": {
            "key": "uniqueObject3:008997"
        }
}
"""

let jsonData = Data(jsonString.utf8)

let decodedData = try? JSONDecoder().decode(JSONData.self, from: jsonData)

print(decodedData?.uniqueObjects.firstObject.firstName ?? "No data decoded")

struct JSONData: Decodable {
    let uniqueObjects: Object
    let keys: KeyObjects
}

struct Object: Decodable {
    let firstObject: Names
    let secondObject: Names
    let thirdObject: Names
    
    private enum DynamicCodingKeys: String, CodingKey {
        case firstObject = "???" // this needs to be mapped to the unique value for object 1
        case secondObject = "??" // this needs to be mapped to the unique value for object 2
        case thirdObject = "????" // etc.
        // I don't think this works because Xcode says that the strings must be raw literals
    }
}

struct KeyObjects: Decodable {
    let object1: Key
    let object2: Key
    let object3: Key
}

struct Key: Decodable {
    let key: String
}

struct Names: Decodable {
    let firstName: String
    let lastName: String
}

The approach I took here, which is definitely wrong, was to create a coding key for each of the unique objects and map its name to a String that would be somehow be decoded from its relative key value pair in the key object. CodingKeys, at least what I have tried, do not allow you to do this so I need a new method in order to access this code. I also need to know how I can reference the data once I decode it (just printing it out for now). Help and a short explanation would be much appreciated as I am a beginner developer. Thanks!

Unless I have misunderstood it looks to me like you are over complicating things. This is how I would define the types for decoding the json

struct Response: Codable {
    let uniqueObjects: [String: User]
    let keys: [String: ObjectKey]
}

struct ObjectKey: Codable {
    let key: String
}

struct User: Codable {
    let firstName: String
    let lastName: String
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM