使用 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]) 属性 转换为更有用的东西,但这超出了这个问题