如何在Swift中从JSON中的不同参数中确定和设置参数的Object类型?

How to determine and set the type of Object of a parameter from a different parameter in JSON in Swift?

提问人:Frankenstein 提问时间:6/22/2022 最后编辑:Frankenstein 更新时间:6/28/2022 访问量:53

问:

如何实现一个解决方案,通过分析与其他参数在同一级别的参数来分析 JSON,从而随时随地设置参数的类型?

let sampleData = Data("""
[
  {
  "type": "one",
  "body": {
    "one": 1
  },
  .
  .
  .
},
  {
  "type": "two",
  "body": {
    "two": 2,
    "twoData": "two"
  },
  .
  .
  .
}
]
""".utf8)

struct MyObject: Codable {
  let type: String
  let body: Body
}

struct Body: Codable {
  let one, two: Int?
  let twoData: String?
}

print(try JSONDecoder().decode([MyObject].self, from: sampleData))

在这里,您可以看到 中的键都是可选的。我的解决方案需要根据参数中给出的值将它们解析为不同的类型。如何根据我收到的值将 body 解析为以下 2 种不同的类型?Bodytypetype

struct OneBody: Decodable {
  let one: Int
}

struct TwoBody: Decodable {
  let two: Int
  let twoData: String
}
iOS JSON Swift 解析 泛型

评论

0赞 Frankenstein 6/22/2022
@Sh_Khan 上面的帖子很有帮助。您能否澄清一下是否有一种方法可以使用参数来确定类型,而不是仅仅尝试使用不同的对象直到成功?
0赞 Sulthan 6/28/2022
类似的问题(和类似的答案)在这里 stackoverflow.com/q/54700409/669586

答:

0赞 Frankenstein 6/28/2022 #1

我最终采用的方法是使用自定义方法,其中首先确定类型,然后使用语句遍历每个类型以解码每个类型并将其作为另一个类型分配给正文。代码如下:init(from decoder: Decoder)switchcaseenum

struct MyObject: Decodable {
  let body: MyBody

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    let type = try container.decode(MyType.self, forKey: .type)
    switch type {
    case .one:
      body = .one(try container.decode(OneBody.self, forKey: .body))
    case .two:
      body = .two(try container.decode(TwoBody.self, forKey: .body))
    }
  }

  enum CodingKeys: String, CodingKey {
    case type, body
  }
}

enum MyType: String, Decodable {
  case one, two
}

enum MyBody: Decodable {
  case one(OneBody)
  case two(TwoBody)
}

struct OneBody: Decodable {
  let one: Int
}

struct TwoBody: Decodable {
  let two: Int
  let twoData: String
}

print(try JSONDecoder().decode([MyObject].self, from: sampleData))

PS:如果有任何更好的方法,请发表答案或评论。