如何从json对象中提取值作为数据?

时间:2019-06-19 06:24:20

标签: json swift

我正在尝试解码json文件,但是它包含元数据,而不仅仅是对象的直接排列。目前,我的解决方案涉及将数据转换为json对象,提取results,然后再将其转换为Data,然后进行解码。它可以工作,但是太乱了。有没有更直接的方法?

我的json文件“ itemsActual.json”:

{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 1,
            "uid": "a019bf6c-44a2-11e9-9121-4ccc6afe39a1",
            "company": "Bioseed",
            "item_class": "Seeds",
            "name": "9909",
            "stock": 0,
            "average_cost": 0.0,
            "otc_price": 0.0,
            "dealer_price": 0.0,
            "ctc_price": 0.0
        },
        {
            "id": 2,
            "uid": "a019bf71-44a2-11e9-9121-4ccc6afe39a1",
            "company": "Pioneer",
            "item_class": "Seeds",
            "name": "4124YR",
            "stock": 0,
            "average_cost": 0.0,
            "otc_price": 0.0,
            "dealer_price": 0.0,
            "ctc_price": 0.0
        }
    ]
}

我只想干净提取类型为Data的结果:

[
    {
        "id": 1,
        "uid": "a019bf6c-44a2-11e9-9121-4ccc6afe39a1",
        "company": "Bioseed",
        "item_class": "Seeds",
        "name": "9909",
        "stock": 0,
        "average_cost": 0.0,
        "otc_price": 0.0,
        "dealer_price": 0.0,
        "ctc_price": 0.0
    },
    {
        "id": 2,
        "uid": "a019bf71-44a2-11e9-9121-4ccc6afe39a1",
        "company": "Pioneer",
        "item_class": "Seeds",
        "name": "4124YR",
        "stock": 0,
        "average_cost": 0.0,
        "otc_price": 0.0,
        "dealer_price": 0.0,
        "ctc_price": 0.0
    }
]

I.E。我想执行以下操作而不必先强制转换为Dictionary,然后重新转换为Data

// What I want to do
let data: Data = try Data(contentsOf: "items.json")
let resultsData: Data = data["results"]

编辑:当前,我正在使用的代码可以实现所需的功能:

let filename = "itemsActual.json"
        guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
        }

        do {
            // Load the json file with metadata
            var data = try Data(contentsOf: file)
            // Split up the string and extract only the value of results
            let str = data.asString().components(separatedBy: "\"results\":")[1].dropLast(3)
            print(str) // Printing here results in just the results

            // Convert back to type Data so I can pass it off to be decoded
            data = str.asData()

        } catch {
            fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
        }

3 个答案:

答案 0 :(得分:1)

let dataContacts = // your array or dict
let data = try JSONEncoder().encode(dataContacts)  // converting to data

答案 1 :(得分:1)

我猜这里的问题是“为什么只需要结果数组的内容?” 您提到您decode个数组,所以我假设这里所需的只是一个包装容器结构,仅用于解码,例如像这样

struct ResultHolder: Decodable {
     let results: [YourCustomType]
}

let resultHolder = try JSONDecoder().decode(ResultHolder.self, from: data) 

//use your array:
print(resultHolder.results)

编辑:

我假设您对API的所有响应(即JSON的来源)都遵循类似的结构。因此,现在是引入泛型的好时机。例如像:

struct ResultHolder<T>: Decodable where T: Decodable {
    let results: [T]
}

答案 2 :(得分:1)

这是最短,最通用的方法,不需要任何额外的编码,如果这对您来说是很多代码,那么我想您的问题的答案是“不,它无法完成”

do {
    let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
    if let results = json["results"] as? [[String: Any]] {
        let dataResults = try JSONSerialization.data(withJSONObject: results)
    }
} catch {
    print(error)
}
相关问题