使用 Swift 解码具有不同结构的 JSON
Decode JSON with different structures with Swift
我有 json 来自 nosql 数据库的具有相同核心结构的数据(PK、SK、属性)。属性部分会根据SK值不同而不同
示例:
[
{
"PK": "POLL#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
"SK": "#METADATA#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
"attributes": {
"latitude": "53.34589121858683",
"longitude": "-6.272215191675388",
"max_choices": 50,
"number": "1544693",
"poll_open": false,
}
},
{
"PK": "POLL#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
"SK": "CHOICE#00a6ec5c-acc1-40f1-a087-31160d2cfc65",
"attributes": {
"distance": 790.95097525,
"latitude": 53.3416,
"price": "€€",
"categories": [
{
"title": "Ramen",
"alias": "ramen"
}
],
"vote_count": 0,
"longitude": -6.26274
}
}
]
是否可以无误地使用解码?我已经坚持了几个小时。
我定义了以下内容:
struct Result: Codable {
var PK: String
var SK: String
var attributes: String
}
但是,当我解码时,出现错误:
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "attributes", intValue: nil)], debugDescription: "Expected to decode String but found a dictionary instead.", underlyingError: nil))
我只想将 'attributes' 解码为通用字符串,然后在我知道如何正确处理它时根据 SK 的值对其进行解析。为什么这么难?
您现在需要属性吗?或者你只是在寻找pk和sk?如果你不需要它就不要包含
var attributes: String
在你的结构中。它不会有解码错误,它会解码其他两个,你只是不会得到 attributes 参数。它无法解码属性
作为一个字符串,因为它不是。它真的更像是一本字典。 Swift 除非你明确告诉它,否则不知道如何处理。话虽这么说,你总是可以做到这一点
struct Result: Codable {
var PK: String
var SK: String
var attributes: Attributes
}
struct Attributes: Codable {
var lattitude: String
var longitude: String
//and whatever else you know you have
}
密钥仅添加您知道将包含在属性中的值,否则会出错
您需要使用 JSONSerialization 而不是 Codable 来处理这个问题。如果您仍然想使用相同的结构,则需要将其更改为
struct Result {
var PK: String
var SK: String
var attributes: [String: Any]
}
并像这样解码 json
var result: Result?
do {
if let dictionary = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let pk = dictionary["PK"] as? String,
let sk = dictionary["SK"] as? String,
let attributes = dictionary["attributes"] as? [String: Any] {
result = Result(PK: pk, SK: sk, attributes: attributes)
}
} catch {
print(error)
}
现在您仍然需要将结果的 attributes
([String: Any]) 属性 转换为更有用的东西,但这超出了这个问题
我有 json 来自 nosql 数据库的具有相同核心结构的数据(PK、SK、属性)。属性部分会根据SK值不同而不同
示例:
[
{
"PK": "POLL#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
"SK": "#METADATA#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
"attributes": {
"latitude": "53.34589121858683",
"longitude": "-6.272215191675388",
"max_choices": 50,
"number": "1544693",
"poll_open": false,
}
},
{
"PK": "POLL#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
"SK": "CHOICE#00a6ec5c-acc1-40f1-a087-31160d2cfc65",
"attributes": {
"distance": 790.95097525,
"latitude": 53.3416,
"price": "€€",
"categories": [
{
"title": "Ramen",
"alias": "ramen"
}
],
"vote_count": 0,
"longitude": -6.26274
}
}
]
是否可以无误地使用解码?我已经坚持了几个小时。
我定义了以下内容:
struct Result: Codable {
var PK: String
var SK: String
var attributes: String
}
但是,当我解码时,出现错误:
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "attributes", intValue: nil)], debugDescription: "Expected to decode String but found a dictionary instead.", underlyingError: nil))
我只想将 'attributes' 解码为通用字符串,然后在我知道如何正确处理它时根据 SK 的值对其进行解析。为什么这么难?
您现在需要属性吗?或者你只是在寻找pk和sk?如果你不需要它就不要包含
var attributes: String
在你的结构中。它不会有解码错误,它会解码其他两个,你只是不会得到 attributes 参数。它无法解码属性 作为一个字符串,因为它不是。它真的更像是一本字典。 Swift 除非你明确告诉它,否则不知道如何处理。话虽这么说,你总是可以做到这一点
struct Result: Codable {
var PK: String
var SK: String
var attributes: Attributes
}
struct Attributes: Codable {
var lattitude: String
var longitude: String
//and whatever else you know you have
}
密钥仅添加您知道将包含在属性中的值,否则会出错
您需要使用 JSONSerialization 而不是 Codable 来处理这个问题。如果您仍然想使用相同的结构,则需要将其更改为
struct Result {
var PK: String
var SK: String
var attributes: [String: Any]
}
并像这样解码 json
var result: Result?
do {
if let dictionary = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let pk = dictionary["PK"] as? String,
let sk = dictionary["SK"] as? String,
let attributes = dictionary["attributes"] as? [String: Any] {
result = Result(PK: pk, SK: sk, attributes: attributes)
}
} catch {
print(error)
}
现在您仍然需要将结果的 attributes
([String: Any]) 属性 转换为更有用的东西,但这超出了这个问题