热解码 JSON 可以和数组的数据或 Swift 中的单个元素?
Hot to decode JSON data that could and array or a single element in Swift?
我有一个名为 Info 的结构,它根据接收到的数据进行解码。但有时,data 中的一个值可以是双精度型或双精度型数组。我该如何为此设置我的结构?
struct Info: Decodable {
let author: String
let title: String
let tags: [Tags]
let price: [Double]
enum Tags: String, Decodable {
case nonfiction
case biography
case fiction
}
}
基于url,我要么得到双倍的价格
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : "242"
}
或者我将其作为双精度数组获取
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : [
"242",
"299",
"335"
]
}
我想设置我的结构,这样如果我收到一个双精度数组而不是双精度数组,价格应该被解码为 1 个双精度数组。
您的 JSON 实际上是一个字符串或一个字符串数组。所以你需要创建一个自定义解码器来解码然后将它们转换为 Double:
struct Info {
let author, title: String
let tags: [Tags]
let price: [Double]
enum Tags: String, Codable {
case nonfiction, biography, fiction
}
}
extension Info: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
author = try container.decode(String.self, forKey: .author)
title = try container.decode(String.self, forKey: .title)
tags = try container.decode([Tags].self, forKey: .tags)
do {
price = try [Double(container.decode(String.self, forKey: .price)) ?? .zero]
} catch {
price = try container.decode([String].self, forKey: .price).compactMap(Double.init)
}
}
}
游乐场测试
let infoData = Data("""
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : "242"
}
""".utf8)
do {
let info = try JSONDecoder().decode(Info.self, from: infoData)
print("price",info.price) // "price [242.0]\n"
} catch {
print(error)
}
let infoData2 = Data("""
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : [
"242",
"299",
"335"
]
}
""".utf8)
do {
let info = try JSONDecoder().decode(Info.self, from: infoData2)
print("price",info.price) // "price [242.0, 299.0, 335.0]\n"
} catch {
print(error)
}
我有一个名为 Info 的结构,它根据接收到的数据进行解码。但有时,data 中的一个值可以是双精度型或双精度型数组。我该如何为此设置我的结构?
struct Info: Decodable {
let author: String
let title: String
let tags: [Tags]
let price: [Double]
enum Tags: String, Decodable {
case nonfiction
case biography
case fiction
}
}
基于url,我要么得到双倍的价格
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : "242"
}
或者我将其作为双精度数组获取
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : [
"242",
"299",
"335"
]
}
我想设置我的结构,这样如果我收到一个双精度数组而不是双精度数组,价格应该被解码为 1 个双精度数组。
您的 JSON 实际上是一个字符串或一个字符串数组。所以你需要创建一个自定义解码器来解码然后将它们转换为 Double:
struct Info {
let author, title: String
let tags: [Tags]
let price: [Double]
enum Tags: String, Codable {
case nonfiction, biography, fiction
}
}
extension Info: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
author = try container.decode(String.self, forKey: .author)
title = try container.decode(String.self, forKey: .title)
tags = try container.decode([Tags].self, forKey: .tags)
do {
price = try [Double(container.decode(String.self, forKey: .price)) ?? .zero]
} catch {
price = try container.decode([String].self, forKey: .price).compactMap(Double.init)
}
}
}
游乐场测试
let infoData = Data("""
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : "242"
}
""".utf8)
do {
let info = try JSONDecoder().decode(Info.self, from: infoData)
print("price",info.price) // "price [242.0]\n"
} catch {
print(error)
}
let infoData2 = Data("""
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : [
"242",
"299",
"335"
]
}
""".utf8)
do {
let info = try JSONDecoder().decode(Info.self, from: infoData2)
print("price",info.price) // "price [242.0, 299.0, 335.0]\n"
} catch {
print(error)
}