Как извлечь значение из объекта JSON в качестве данных? - PullRequest
0 голосов
/ 19 июня 2019

Я пытаюсь декодировать файл 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
    }
]

т.е. Я хочу сделать следующее без необходимости сначала приводить в 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 ]

1 голос
/ 19 июня 2019

Я предполагаю, что вопрос здесь "Зачем вам нужно только содержимое массива результата?" Вы упоминаете, что вы decode массив, так что я предполагаю, что вам здесь нужна только структура контейнера-обертки только для декодирования, например как то так

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

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

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

Edit:

Я предполагаю, что все ваши отклики от API (то есть, откуда JSON, справа) имеют сходную структуру. Итак, сейчас самое время представить дженерики. например как:

struct ResultHolder<T>: Decodable where T: Decodable {
    let results: [T]
}
1 голос
/ 19 июня 2019

Это самый короткий и общий способ сделать это без какого-либо дополнительного кодирования. Если это слишком много кода для вас, то я думаю, что ответ на ваш вопрос «нет, это не может быть сделано»

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)
}
1 голос
/ 19 июня 2019
let dataContacts = // your array or dict
let data = try JSONEncoder().encode(dataContacts)  // converting to data
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...