首页 > 解决方案 > 快速解码复合结构数据

问题描述

我有以下 json 数据并试图解析它,但我得到了对象的数量,但数组中的对象本身都是零。

我不想解码origin下面的 json 对象。

顺便说一句,下面的字符串首先转换为数据,然后将其传递给parse下面的函数。

数据如下:

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

楷模

struct A: Codable {
    let id: String?
    let age: Int?

    enum CodingKeys: String, CodingKey {
        case id
        case age
    }
}

struct B: Codable {
    let character, isDead, canMove: String?

    enum CodingKeys: String, CodingKey {
        case character
        case isDead
        case canMove
    }
}

struct AB :Codable {
  let a: A
  let b: B

  init(from decoder: Decoder) throws {
    guard var container = try? decoder.unkeyedContainer() else { 
         //no error here!!!       
         fatalError()   
     }
    print(container)
    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.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: nil)
        )
      }
    self.a = a
    self.b = b
  }
}

视图模型

private func parse(jsonData : Data){
    do {
        let decoder = JSONDecoder()
        let response = try decoder.decode([AB].self, from: jsonData)
        print(response)
    }
    catch (let error as NSError) {
        print(error)
    }
}

更新: 顺便说一句,以下代码有效。我想知道为什么上面的代码不能处理?

private func parseData(jsonData : Data)
{
    do {
        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 b = try JSONDecoder().decode(A.self, from: jsonDat)
                }
                else if j == 1
                {
                    let jsonDatt = (try? JSONSerialization.data(withJSONObject:response[i][j]))!
                    let a = try JSONDecoder().decode(B.self, from: jsonDatt)
                }
            }
        }
        print(response)
    }
    catch let error as NSError {
        print(error)
    }
}

更新二:

如果我进行以下更改[AB]--> [[AB]],然后按如下方式调用它,它会解码数据,但在我最终得到的数组中,A 对象有值,但 B 为零,反之亦然。

let response = try decoder.decode([[AB]].self, from: jsonData)


guard var container = try? decoder.singleValueContainer() else
{
    fatalError()
}

标签: swiftdecodejsondecoder

解决方案


我刚刚在操场上尝试了您的代码的精简版本

let json = """
[
 [
   {"id": "152478", "age": 20},
   {"character": "king","isDead":"no", "canMove" :"yes", "origin" :"south africa"}
 ],
 [
  {"id": "887541", "age": 22},
  {"character": "lion", "isDead":"no", "canMove" :"yes", "origin" :"south america"}
 ]
]
""".data(using: .utf8)!

struct A: Codable {
    let id: String
    let age: Int
}

struct B: Codable {
    let character, isDead, canMove: String
}

struct AB: Codable {
    let a: A
    let b: B

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

        self.a = try container.decode(A.self)
        self.b = try container.decode(B.self)
    }
}

do {
    let ab = try JSONDecoder().decode([AB].self, from: json)
    print(ab.count)
    print(ab[0].a.id)
    print(ab[0].b.character)

    print(ab[1].a.id)
    print(ab[1].b.character)
} catch {
    print(error)
}

它工作得很好。也许这有助于弄清楚发生了什么。


推荐阅读