1

The API I am using supports multi-language. For instance:

// For Japanese
{
    "earthquake_detail": {
        "advisory_title_ja": "津波注意報",
        "depth_title_ja": "震源深さ",
        "depth_value_ja": "30km",
    }
}

// For English

{
    "earthquake_detail": {
        "advisory_title_en": "Tsunami Advisory",
        "depth_title_en": "Depth",
        "depth_value_en": "30km",       
    }
}

I am using swift codable to map them to a struct. Is there a way that I can map multiple coding keys to a single variable? Here is my swift struct.

struct EarthquakeDetail: Codable {
    var advisoryTitle, depthTitle, depthValue: String?

    enum CodingKeys: String, CodingKey {
        case advisoryTitle = "advisory_title_ja"
        case depthTitle = "depth_title_ja"
        case depthValue = "depth_value_ja"
    }
}

What I want to obtain is for Japanese this will be the coding keys:

enum CodingKeys: String, CodingKey {
            case advisoryTitle = "advisory_title_ja"
            case depthTitle = "depth_title_ja"
            case depthValue = "depth_value_ja"
        }

and for English:

enum CodingKeys: String, CodingKey {
            case advisoryTitle = "advisory_title_en"
            case depthTitle = "depth_title_en"
            case depthValue = "depth_value_en"
        }

1 Answer 1

2

If you are not going to use the convertFromSnakeCase strategy add a custom key decoding strategy which drops the _xx from the three coding keys.

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .custom { codingKeys in
    let lastKey = codingKeys.last!
    if lastKey.intValue != nil || codingKeys.count != 2 { return lastKey }
    if codingKeys.dropLast().last!.stringValue != "earthquake_detail" { return lastKey }
    return AnyCodingKey(stringValue: String(lastKey.stringValue.dropLast(3)))!
}

If the earthquake_detail key is deeper than on level 2 change != 2 accordingly

To be able to create custom coding keys you need

struct AnyCodingKey: CodingKey {
    var stringValue: String
    var intValue: Int?

    init?(stringValue: String) { self.stringValue = stringValue }

    init?(intValue: Int) {
        self.stringValue = String(intValue)
        self.intValue = intValue
    }
}

Now declare EarthquakeDetail as follows

struct EarthquakeDetail: Codable {
    var advisoryTitle, depthTitle, depthValue: String

    enum CodingKeys: String, CodingKey {
        case advisoryTitle = "advisory_title"
        case depthTitle = "depth_title"
        case depthValue = "depth_value"
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.