Codable:按键解码

时间:2018-05-25 21:04:21

标签: swift codable

假设我有一个返回此json的API:

{
   "dogs": [{"name": "Bella"}, {"name": "Lucy"}], 
   "cats": [{"name": "Oscar"}, {"name": "Coco"}]
}

一个看起来像这样的模型:

import Foundation

public struct Animal: Codable {
    let name: String?
}

现在我想从“狗”键解码动物数组:

let animals = try JSONDecoder().decode([Animal].self, from: response.data!)

但是,我不知何故必须参考“狗”键。我该怎么做?

4 个答案:

答案 0 :(得分:2)

首先,您提供的JSON不是有效的JSON。所以让我们假设你的意思是:

{
    "dogs": [{"name": "Bella"}, {"name": "Lucy"}],
    "cats": [{"name": "Oscar"}, {"name": "Coco"}]
}

然后你的代码问题只是这一行:

let animals = try JSONDecoder().decode([Animal].self, from: response.data!)

您声称JSON代表一个Animal数组。但事实并非如此。它代表一个包含密钥dogscats的字典。所以你只是这么说。

struct Animal: Codable {
    let name: String
}
struct Animals: Codable {
    let dogs: [Animal]
    let cats: [Animal]
}

现在一切都会奏效:

let animals = try JSONDecoder().decode(Animals.self, from: response.data!)

答案 1 :(得分:0)

您可以从JSON获取所有值,如下所示:

let arrayOfResponse = Array(response.data.values)
let clinicalTrial = try JSONDecoder().decode([Animal].self, from: arrayOfResponse!)

答案 2 :(得分:0)

如果你知道以前像狗一样的钥匙,你可以像这样做猫

   struct Initial: Codable {
        let dogs, cats: [Animal]
    }

    struct Animal: Codable {
        let name: String
    }

    // MARK: Convenience initializers

    extension Initial {
        init(data: Data) throws {
            self = try JSONDecoder().decode(Initial.self, from: data)
        }

        init(_ json: String, using encoding: String.Encoding = .utf8) throws {
            guard let data = json.data(using: encoding) else {
                throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
            }
            try self.init(data: data)
        }
    }


// data  is your response data

  if let inital = try? Initial.init(data: data) {
                let cats = inital.cats
                let dogs = inital.dogs
            }

答案 3 :(得分:0)

您的JSON略有偏离,您必须在name周围放置双引号,但这样您就可以运行以下游乐场:

import Cocoa

let jsonData = """
{
   "dogs": [{"name": "Bella"}, {"name": "Lucy"}],
   "cats": [{"name": "Oscar"}, {"name": "Coco"}]
}
""".data(using: .utf8)!

public struct Animal: Codable {
    let name: String
}

do {
    let anims = try JSONDecoder().decode([String:[Animal]].self, from:jsonData)
    print(anims)
    for kind in anims.keys {
        print(kind)
        if let examples = anims[kind] {
            print(examples.map {exa in exa.name })
        }
    }
} catch {
    print(error)
}

这不会将您限制为catsdogs,但使用“未知”键作为哈希中的数据元素通常是个坏主意。如果你可以修改你的JSON(你应该这样做,因为它的结构不是很好),你也可以将动物的“种类”移动到散列数组中的某些数据元素,这将更加灵活。 / p>