Кодируемый: декодирование по ключу - PullRequest
0 голосов
/ 26 мая 2018

Предположим, у меня есть API, который возвращает этот json:

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

И модель, которая выглядит следующим образом:

import Foundation

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

Теперь я хочу декодировать массив Animal изключ "dogs":

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

Однако мне как-то приходится ссылаться на ключ "dogs".Как мне это сделать?

Ответы [ 4 ]

0 голосов
/ 26 мая 2018

Ваш 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)
}

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

0 голосов
/ 26 мая 2018

если вы знаете ключи ранее, как собаки, кошки, вы можете сделать так

   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
            }
0 голосов
/ 26 мая 2018

Прежде всего, указанный вами JSON не является допустимым JSON.Итак, давайте предположим, что вы на самом деле имеете в виду следующее:

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

Тогда проблема с вашим кодом заключается просто в следующей строке:

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

Вы утверждаете, что JSON представляет массивживотных.Но это не так.Он представляет собой словарь с ключами dogs и cats.Так что вы просто так говорите.

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!)
0 голосов
/ 26 мая 2018

Вы можете получить все значения из JSON следующим образом:

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