使用 JSONDecoder 解码数字 snake_case 键

Posted

技术标签:

【中文标题】使用 JSONDecoder 解码数字 snake_case 键【英文标题】:Decoding numerical snake_case keys with JSONDecoder 【发布时间】:2019-06-27 01:13:31 【问题描述】:

我有以下 JSON 对象,将使用 JSONDecoder 将其转换为对象:


  "first_key": 3,
  "image_1000x1000": "location"

这映射到以下 Swift 模型:

struct Response: Decodable 
  var firstKey: Int
  var image1000x1000: String

通过使用JSONDecoder.convertFromSnakeCase 选项,JSON 中的snake_case 键通过使用the algorithm defined in the documentation 转换为camelCase:

此策略遵循以下步骤将 JSON 键转换为驼峰式:

    将下划线后的每个单词大写。

    删除所有不在字符串开头或结尾的下划线。

    将单词组合成一个字符串。

因此,在这种情况下:

first_key 变为 firstKey(如预期) image_1000x1000 应该变成 image1000x1000

但是,当尝试解码此响应时,会引发image1000x1000 键的keyNotFound 错误 (see this live example):

let json = "\"first_key\": 3, \"image_1000x1000\": \"location\"".data(using: .utf8)!
do 
  let decoder = JSONDecoder()
  decoder.keyDecodingStrategy = .convertFromSnakeCase
  let response = try decoder.decode(Response.self, from: json)
  print(response)
 catch let e 
  print(e)

我的image_1000x1000的驼峰式转换有什么不对,为什么JSONDecoder找不到对应的key?

【问题讨论】:

你的结构属性被命名为image,而不是image1000x1000 @rmaddy 这就是我使用CodingKeys 将JSON 键映射到相应的image 属性的原因 我可能弄错了,但是如果您在 CodingKeys 枚举中明确列出映射,则 keyDecodingStrategy 不会应用于该对。使用现有的密钥解码策略,如果您删除了 image/image_1000x1000 的显式 CodingKeys 条目并且您的属性被命名为 image1000x1000,它将起作用。如果您想要名为 image 的属性,那么您需要 CodingKeys 条目,就像您最初拥有的一样,以便它与实际的 JSON 键匹配。 是的,无论是否使用CodingKeys,问题仍然存在(见编辑) 简单。只是不要使用 convertFromSnakeCase 并使用 struct Response: Decodable let firstKey: Int let image1000x1000: String private enum CodingKeys: String, CodingKey case firstKey = "first_key", image1000x1000 = "image_1000x1000" 【参考方案1】:

您可以通过反向运行该过程来查看算法的预期;使用JSONEncoder 对数据进行编码并检查输出:

struct Response: Codable 
    var firstKey: Int
    var image1000x1000: String


let test = Response(firstKey: 10, image1000x1000: "secondKey" )

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(test)
print(String(data: data, encoding: .utf8)!)

这将产生:

"first_key":10,"image1000x1000":"secondKey"

因此,如果您可以控制 JSON 并且可以使用 image1000x1000 作为密钥,那么您就完成了。如果没有,你将不得不做这样的事情:

struct Response: Codable 
    var firstKey: Int
    var image1000x1000: String

    private enum CodingKeys: String, CodingKey 
        case image1000x1000 = "image_1000x1000"
        case firstKey = "first_key"
    

另一种选择是实施自定义键编码策略。它可能最终会减少代码。有关更多信息,请参阅KeyEncodingStrategy。

【讨论】:

【参考方案2】:

我面临同样的问题,我的 json 密钥是 iso639_1 和 iso639_2。无需添加 Coding 密钥即可使用。

使您的变量可选

这是我的可解码模型

struct CountryModel: Decodable
    var name: String
    var borders: [String]
    var region: String
    var alpha2Code: String
    var alpha3Code: String
    var flag: String
    var languages: [languages]


struct languages: Decodable 
    var iso639_1: String?
    var iso639_2: String?
    var name: String
    var nativeName: String

当我为下划线变量 iso639_1 和 iso639_2 添加可选时。那么它工作正常可能是由于 Null 值!

在这里,在您的情况下,将可选选项添加到您的 image1000x1000 变量中。如下所示

struct Response: Decodable 
  var firstKey: Int
  var image_1000x1000: String?

希望它会起作用!

【讨论】:

以上是关于使用 JSONDecoder 解码数字 snake_case 键的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 JSONDecoder 返回或解码数据

使用 JSONDecoder 解码古怪的日期格式

如何使用 JSONDecoder 解码自定义 JSON 值

Swift - 使用 JSONDecoder 解码 JSON 数据

如何在 swift 4.1 和 xcode 9.3 中使用 JSONDecoder 解码嵌套的 JSON 数组和对象?

使用 JSONDecoder Swift 解码具有整数值的字符串键 [关闭]