4

我正在尝试解码以下 JSON 对象

{
    "result":[
             {
             "rank":12,
             "user":{ 
                     "name":"bob","age":12 
                    } 
             }, 
             {
             "1":[ 
                  {
                    "name":"bob","age":12
                  },
                  {
                   "name":"tim","age":13
                  }, 
                  {
                   "name":"tony","age":12
                  }, 
                  {
                   "name":"greg","age":13
                  } 
                 ] 
            } 
           ] 
}

struct userObject { 变量名称:字符串变量年龄:整数 }

基本上是具有两种不同对象类型的 JSON 数组

{ "rank":12, "user": {userObject} }

和一个“1”:数组[userObjects]

struct data: Decodable {
   rank: Int
   user: user
   1:    [user]  <-- this is one area Im stuck
}

提前致谢

4

2 回答 2

9

纯娱乐:

首先,您需要用户的结构以及result数组中第一个和第二个字典的表示形式。键"1"映射到one

struct User : Decodable {
    let name : String
    let age : Int
}

struct FirstDictionary : Decodable {
    let rank : Int
    let user : User
}

struct SecondDictionary : Decodable {
    let one : [User]

    private enum CodingKeys: String, CodingKey { case one = "1" }
}

现在是棘手的部分:

  • 首先获取根容器。
  • 获取resultas的容器,nestedUnkeyedContainer因为该对象是一个数组。
  • 解码第一个字典并复制值。
  • 解码第二个字典并复制值。

    struct UserData: Decodable {
    
        let rank : Int
        let user : User
        let oneUsers : [User]
    
       private enum CodingKeys: String, CodingKey { case result }
    
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            var arrayContainer = try container.nestedUnkeyedContainer(forKey: .result)
            let firstDictionary = try arrayContainer.decode(FirstDictionary.self)
            rank = firstDictionary.rank
            user = firstDictionary.user
            let secondDictionary = try arrayContainer.decode(SecondDictionary.self)
            oneUsers = secondDictionary.one
        }
    }
    

如果此代码比传统手册 JSONSerialization更可取,则是另一个问题。

于 2018-02-13T11:09:13.263 回答
0

如果你的 JSON 格式是给定的,那么你很不走运,因为你很可能必须按原样解析你的数组[Any],委婉地说,不是很有用。另一方面,如果您能够修改 JSON 的格式,您应该从另一个方向开始。定义您想要的 Swift 对象并使用它对其进行编码JSONEncoder.encode(...),以便快速确定您的 JSON 应该是什么样子,以便使其以尽可能键入的方式解析。

这种方法很容易将您的 JSON 处理代码减半,因为您的 Web 服务协议最终会变得更好。这可能会改善整个系统的结构,因为它将产生更稳定的通信协议。

可悲的是,这种方法并不总是可行的,因为当事情变得混乱时。鉴于您的示例,您将能够将代码解析为

let st = """
{
    "result":[
        {
            "rank":12,
            "user":{
                "name":"bob",
                "age":12
            }
        },
        {
            "1":[
                {
                    "name":"bob","age":12
                },
                {
                    "name":"tim","age":13
                },
                {
                    "name":"tony","age":12
                },
                {
                    "name":"greg","age":13
                }
            ]
        }
    ]
}
"""

let jsonData1 = st.data(using: .utf8)!
let arbitrary = try JSONSerialization.jsonObject(with: jsonData1, options: .mutableContainers)

这将允许您使用一堆强制转换访问您的数据,如

let dict = arbitrary as! NSDictionary
print(dict["result"])

你明白了。不是很有用,因为您非常想使用Codable协议,如

 struct ArrayRes : Codable {
     let result : [[String:Any]]
 }

 let decoder1 = JSONDecoder()
 do {
     let addrRes = try decoder.decode(ArrayRes.self, from: jsonData1)
        print(addrRes)
     } catch {
        print("error on decode: \(error.localizedDescription)")
 }

不幸的是,这不起作用,因为Any不是Codable出于稍微明显的原因。

我希望您能够更改您的 JSON 协议,因为当前的协议将是许多混乱代码的根本原因。

于 2018-02-13T07:31:21.950 回答