使用 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 键的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 使用 JSONDecoder 解码 JSON 数据