是否存在为 swift Codable 中存在的密钥提供替代值的 GSON java 库功能?

问题描述

我遇到了一个 API,我必须重用我现有的 Codable 模型之一来解析 JSON。但是,“service_name”键在新 API 中被命名为“name”。我向我的 android 开发人员询问了他如何使用相同的模型解析该 JSON。他告诉我,在用于在 android 中解析的 GSON 库中也有相同的支持代码如下

@Serializedname(value = "service_name",alternate = ["name"])

我想知道这是否可以在 Codable 中以直接的方式实现。我知道这可以通过变通办法来实现。但是 Swift Codable 是否支持开箱即用的功能

我的要求:

API JSON 响应 1

API JSON Response 1

API 2 JSON 响应

enter image description here

我正在使用如下模型进行解析

// MARK: - CustomerOtherServiceResponseModel
struct CustomerOtherServiceResponseModel:Decodable {
    let name:String
    let externalLink:String?
    let type:ServiceType
}

是否可以对两个 API 使用相同的模型?。编码键只能映射到一个属性,对吗?。或者有没有其他方法可以使用相同的模型来做同样的事情。

解决方法

这可以通过实现自定义 init(from:) 来解决,我们首先尝试解码“name”键,如果这不起作用,我们尝试使用“service_name”键。 对于第二个键,我们使用与我们合成的不同的 CodingKey 枚举创建一个新的容器对象。

struct Service: Codable {
    let name: String
    let id: Int
    let type: String

    enum OtherApiKeys: String,CodingKey {
        case name = "service_name"
    }
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self,forKey: .id)
        if let value = try? container.decodeIfPresent(String.self,forKey: .name) {
            name = value
        } else {
            let otherContainer = try decoder.container(keyedBy: OtherApiKeys.self)
            name = try otherContainer.decode(String.self,forKey: .name)
        }
        type = try container.decode(String.self,forKey: .type)
    }
}

由于您发布的 json 和 struct 代码不匹配,因此我在这里使用了自己的 struct 和 json,但应该很容易翻译。下面是我的测试数据和代码

let data1 = """
{
    "id": 157,"name": "Some name","type": "hair"
}
""".data(using: .utf8)!

let data2 = """
{
    "id": 158,"service_name": "Some name","type": "hair"
}
""".data(using: .utf8)!

do {
    let decoder = JSONDecoder()

    for data in [data1,data2] {
        let result = try decoder.decode(Service.self,from: data)
        print(result)
    }
} catch {
    print(error)
}