Несколько ключей кодирования для отдельных данных в Codable - PullRequest
1 голос
/ 26 марта 2020

API, который я использую, поддерживает многоязычность. Например:

// 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",       
    }
}

Я использую swift codable, чтобы отобразить их в структуру. Есть ли способ, которым я могу сопоставить несколько ключей кодирования одной переменной? Вот моя быстрая структура.

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"
    }
}

То, что я хочу получить, это для японского языка это будут ключи кодирования:

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

и для Engli sh:

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

1 Ответ

1 голос
/ 26 марта 2020

Если вы не собираетесь использовать стратегию convertFromSnakeCase, добавьте собственную стратегию декодирования ключей, которая удаляет _xx из трех кодирующих клавиш.

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)))!
}

Если клавиша earthquake_detail глубже чем на уровне 2 изменить != 2 соответственно

Чтобы иметь возможность создавать собственные ключи кодирования, вам нужно

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
    }
}

Теперь объявите EarthquakeDetail следующим образом

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

    enum CodingKeys: String, CodingKey {
        case advisoryTitle = "advisory_title"
        case depthTitle = "depth_title"
        case depthValue = "depth_value"
    }
}
...