Swift json json 的动态密钥解析
Swift json dynamic key parsing for json
我有 json 响应,其中只有一个键名更改其余部分是相同的,并且想在不重复相同结构的情况下进行解析。
"attributes": {
"symbol":"EUR",
"name":"Euro",
"precision":2,
}
"attributes":{
"symbol":"EUR",
"name":"Euro",
"precision_for_fiat_price":2,
}
如何在json解析
中动态处理这个精度键
您可以使用自定义 keyDecodingStrategy
。
本质上,您编写了一些逻辑来检查当前编码键路径是否符合某些条件,如果符合,则将该键映射到 precision
键。
例如:
struct Root : Codable {
let attributes: Attributes
}
struct Attributes : Codable {
let symbol: String
let name: String
let precision: Int
enum CodingKeys: CodingKey {
case symbol
case name
case precision
}
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .custom({
keys in
// This will decode every precision_for_fiat_price key in the json as "precision".
// You might not want this.
// Make this criteria stricter if you need to. An example is shown below
if keys.last?.stringValue == "precision_for_fiat_price" {
return Attributes.CodingKeys.precision
}
// this will only decode those precision_for_fiat_price that have "attribute" as their parent as "precision"
// if stringPath.suffix(2) == ["attributes", "precision_for_fiat_price"] {
// return Attributes.CodingKeys.precision
// }
return keys.last!
})
let json = """
{
"attributes":{
"symbol":"EUR",
"name":"Euro",
"precision_for_fiat_price":2
}
}
""".data(using: .utf8)!
let decoded = try decoder.decode(Root.self, from: json)
如果你只想像这样解码 json 模型:
let json = """
{
"attributes": {
"symbol":"EUR",
"name":"Euro",
"precision_for_fiat_price":2 // or "precision": 2
}
}
"""
您可以创建 Decodable
结构:
struct WrapperModel: Decodable { // any model
var attributes: Attributes
}
struct Attributes : Decodable {
let symbol: String
let name: String
var precision: Int = 0
enum CodingKeys: String, CodingKey, CaseIterable {
case symbol
case name
case precision
case precisionAnother = "precision_for_fiat_price"
// you can write any types of key here
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
symbol = try container.decode(String.self, forKey: .symbol)
name = try container.decode(String.self, forKey: .name)
if let precisionValue = try container.decodeIfPresent(Int.self, forKey: .precision) {
precision = precisionValue
}
if let precisionValue = try container.decodeIfPresent(Int.self, forKey: .precisionAnother) {
precision = precisionValue
}
}
}
您可以使用以下方法进行测试:
let jsonData = Data(json.utf8)
let decoder = JSONDecoder()
do {
let attributes = try decoder.decode(WrapperModel.self, from: jsonData)
print(attributes)
} catch {
print(error.localizedDescription)
}
我有 json 响应,其中只有一个键名更改其余部分是相同的,并且想在不重复相同结构的情况下进行解析。
"attributes": {
"symbol":"EUR",
"name":"Euro",
"precision":2,
}
"attributes":{
"symbol":"EUR",
"name":"Euro",
"precision_for_fiat_price":2,
}
如何在json解析
中动态处理这个精度键您可以使用自定义 keyDecodingStrategy
。
本质上,您编写了一些逻辑来检查当前编码键路径是否符合某些条件,如果符合,则将该键映射到 precision
键。
例如:
struct Root : Codable {
let attributes: Attributes
}
struct Attributes : Codable {
let symbol: String
let name: String
let precision: Int
enum CodingKeys: CodingKey {
case symbol
case name
case precision
}
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .custom({
keys in
// This will decode every precision_for_fiat_price key in the json as "precision".
// You might not want this.
// Make this criteria stricter if you need to. An example is shown below
if keys.last?.stringValue == "precision_for_fiat_price" {
return Attributes.CodingKeys.precision
}
// this will only decode those precision_for_fiat_price that have "attribute" as their parent as "precision"
// if stringPath.suffix(2) == ["attributes", "precision_for_fiat_price"] {
// return Attributes.CodingKeys.precision
// }
return keys.last!
})
let json = """
{
"attributes":{
"symbol":"EUR",
"name":"Euro",
"precision_for_fiat_price":2
}
}
""".data(using: .utf8)!
let decoded = try decoder.decode(Root.self, from: json)
如果你只想像这样解码 json 模型:
let json = """
{
"attributes": {
"symbol":"EUR",
"name":"Euro",
"precision_for_fiat_price":2 // or "precision": 2
}
}
"""
您可以创建 Decodable
结构:
struct WrapperModel: Decodable { // any model
var attributes: Attributes
}
struct Attributes : Decodable {
let symbol: String
let name: String
var precision: Int = 0
enum CodingKeys: String, CodingKey, CaseIterable {
case symbol
case name
case precision
case precisionAnother = "precision_for_fiat_price"
// you can write any types of key here
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
symbol = try container.decode(String.self, forKey: .symbol)
name = try container.decode(String.self, forKey: .name)
if let precisionValue = try container.decodeIfPresent(Int.self, forKey: .precision) {
precision = precisionValue
}
if let precisionValue = try container.decodeIfPresent(Int.self, forKey: .precisionAnother) {
precision = precisionValue
}
}
}
您可以使用以下方法进行测试:
let jsonData = Data(json.utf8)
let decoder = JSONDecoder()
do {
let attributes = try decoder.decode(WrapperModel.self, from: jsonData)
print(attributes)
} catch {
print(error.localizedDescription)
}