我有以下形状的api响应-
{
"textEntries":{
"summary":{
"id":"101e9136-efd9-469e-9848-132023d51fb1",
"text":"some text",
"locale":"en_GB"
},
"body":{
"id":"3692b0ec-5b92-4ab1-bc25-7711499901c5",
"text":"some other text",
"locale":"en_GB"
},
"title":{
"id":"45595d27-7e06-491e-890b-f50a5af1cdfe",
"text":"some more text again",
"locale":"en_GB"
}
}
}
我想通过JSONDecoder
对此进行解码,以便可以使用属性。我面临的挑战是密钥,在这种情况下,summary
,body
和title
是在其他位置生成的,并不总是这些值,它们始终是唯一的,但是基于产品其他位置发生的逻辑,因此对其他内容文章的另一次调用可能返回leftBody
或subTitle
等。
这些道具的主体模型始终是相同的,但是,我可以期望在任何响应组合中都存在相同的字段。
我将需要能够在其他地方访问代码中每个键的主体。另一个API响应会告诉我我需要的密钥。
我不确定如何使用Decodable
处理此操作,因为我无法提前输入值。
我曾考虑过对人体建模-
struct ContentArticleTextEntries: Decodable {
var id: String
var text: String
var locale: Locale
}
并将值存储在--p这样的结构中
struct ContentArticle: Decodable {
var textEntries: [String: ContentArticleTextEntries]
private enum CodingKeys: String, CodingKey {
case textEntries
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.textEntries = try values.decode(ContentArticleTextEntries.self, forKey: .textEntries)
}
}
我可以让他们在其他地方使用下标来访问属性,但是我不知道如何解码为这种形状,因为上面的方法不起作用。
所以我以后会像textEntries["body"]
这样访问。
我也不知道是否有更好的方法来处理此问题。
我曾考虑过使用枚举将键转换为“类型”,但同样由于事先不知道枚举的情况,因此无法实现。
我知道textEntries不会更改,并且我知道id,text和locale不会更改。我不知道这是这层之间的关键。我尝试了@vadian发布的有用的解决方案,但似乎在仅需要解码一组密钥的情况下无法使这项工作有效。
答案 0 :(得分:1)
对于this answer中提出的解决方案,结构是
struct ContentArticleTextEntries: Decodable {
let title : String
let id: String
let text: String
let locale: Locale
enum CodingKeys: String, CodingKey {
case id, text, locale
}
init(from decoder: Decoder) throws {
self.title = try decoder.currentTitle()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.text = try container.decode(String.self, forKey: .text)
let localeIdentifier = try container.decode(String.self, forKey: .locale)
self.locale = Locale(identifier: localeIdentifier)
}
}
struct ContentArticle: TitleDecodable {
let title : String
var elements: [ContentArticleTextEntries]
}
struct Container: Decodable {
let containers: [ContentArticle]
init(from decoder: Decoder) throws {
self.containers = try decoder.decodeTitledElements(ContentArticle.self)
}
}
然后解码Container.self
答案 1 :(得分:0)
使用“ decodeIfPresent”变体方法代替解码方法,您还需要将ContentArticleTextEntries字典分解为单独的键:
const Account = require('../../model/account')
答案 2 :(得分:0)
如果您的模特很喜欢,
struct ContentArticle: Decodable {
let textEntries: [String: ContentArticleTextEntries]
}
struct ContentArticleTextEntries: Decodable {
var id: String
var text: String
var locale: String
}
然后,您可以像这样简单地基于key
访问数据,
let response = try JSONDecoder().decode(ContentArticle.self, from: data)
let key = "summary"
print(response.textEntries[key])
注意:如果在解析JSON时没有特殊处理,则无需编写enum CodingKeys
和init(from:)
。