【问题标题】:Decode json object in Swift在 Swift 中解码 json 对象
【发布时间】:2020-06-10 02:03:08
【问题描述】:

我有一个 json 文件并读取它并按如下方式对其进行解码。 我的 json 文件如下所示,A 和 B 代表 struct 对象。我想知道有没有更好更有效的方法来解码这种类型的json?

[ 
 [
   {"id": "152478", "age": "20"},{"character": "king", "isDead":"no", "canMove" :"yes"}
 ],
 [
  {"id": "887541", "age": "22"},{"character": "lion", "isDead":"no", "canMove" :"yes"}
 ]
]

解码如下:

    let url = Bundle.main.url(forResource: "mypew", withExtension: "json")!
        do {

        let jsonData = try Data(contentsOf: url)

         // B -> json[0][0], [1][0]
         // A -> json[0][1], [0][1]

        response = try JSONSerialization.jsonObject(with: jsonData) as! [[[String: Any]]]
        for i in 0..<response.count
        {
            for j in 0..<response[i].count
            {
                if j == 0
                {
                    let jsonDat = (try? JSONSerialization.data(withJSONObject:response[i][j]))!
                    let bElement = try JSONDecoder().decode(B.self, from: jsonDat)
                    self.bArray.append(bElement)
                }
                else if j == 1
                {
                    let jsonDatt = (try? JSONSerialization.data(withJSONObject:response[i][j]))!
                    let aElement = try JSONDecoder().decode(A.self, from: jsonDatt)
                    self.aArray.append(aElement)
                }
            }
        }

【问题讨论】:

  • 您希望最终结果是什么样的?如果我正确理解了您的代码,看起来您想要 2 个单独的数组?还是有一些结构可以容纳一对?
  • 我将在自定义表格视图单元格中显示此信息。是的,每个数组项包含 2 个 json 对象。
  • 你的意思是,你想要struct Pair { let a: A; let b: B } 之类的东西,以及这些东西的数组吗?
  • 是的,如果可能的话,我想这样。

标签: swift


【解决方案1】:

首先,使两个对象(我们称它们为AB)符合Decodable

struct A: Decodable {
    var id, age: String
}

struct B: Decodable {
    var character, isDead, canMove: String
}

然后,如果您的 AB 对的结构始终相同,即始终为 [A, B],那么您可以将这对解码为自己的对象。我们称该对象为ABPair

struct ABPair: Decodable {
  let a: A
  let b: B

  init(from decoder: Decoder) throws {
    var container = try decoder.unkeyedContainer()

    guard let a = try? container.decode(A.self), 
          let b = try? container.decode(B.self) 
      else {
        // throw since we didn't find A first, followed by B
        throw DecodingError.dataCorruptedError(in: container, debugDescription: "error")
      }

    self.a = a
    self.b = b
  }
}

您可以按如下方式解码对数组:

let decoder = JSONDecoder()
let pairs = try? decoder.decode([ABPair].self, from: jsonData)
print(pairs[1].b.character) // lion

【讨论】:

  • 我得到 Cannot use mutating member on immutable value: 'container' is immutable in the ABPAir Struct in the guard statement,知道吗?
  • 非常感谢,您能否检查以下问题,它是对该解决方案的跟进。 stackoverflow.com/questions/62336022/…
【解决方案2】:

首先,您需要为模型创建一个Codable 结构。然后从数据而不是 JSON 对象中解码模型。这里是代码,

型号:

struct Model: Codable {
    let id, age, character, isDead, canMove: String?
}

解码:

let url = Bundle.main.url(forResource: "mypew", withExtension: "json")!
do {
    let jsonData = try Data(contentsOf: url)
    let models = try JSONDecoder().decode([[Model]].self, from: jsonData)
    for model in models {
        print(model[0].age, model[1].canMove)
    }
} catch {
    print(error)
}

【讨论】:

  • 那么你如何打印出canMoveage,因为它们都位于不同的对象中?
  • JSON 结构有点奇怪,所以你应该提供数组索引来获取属性的值,比如print(response[0][0].age, response[0][1].canMove)。也许你应该要求后端修改这个 JSON 模型。
猜你喜欢
  • 1970-01-01
  • 2020-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-22
  • 1970-01-01
相关资源
最近更新 更多