Использование декодируемого Swift для вложенных массивов строк

Я пытаюсь декодировать массив строк, где в возвращаемом JSON есть массив строк, но он также содержит вложенные массивы.

IE: JSON:

{ "people": ["Alice", "Bob"], 
"departments": [["Accounts", "Sales"]]
}

Быстрый:

let decoder = JSONDecoder()
let model = try decoder.decode([String:[String]].self, from: dataResponse)
print(model as Any)

Я хочу иметь возможность декодировать отделы, но каждый раз, когда я это делаю, он жалуется, что:

Тип ошибкиMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [_DictionaryCodingKey(stringValue: "departments", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Ожидается декодирование Строка, но вместо этого найден массив.", baseError: nil))

Я понимаю, что это потому, что декодер ожидает строку с массивом строк

Мне интересно, могу ли я также сказать, что он ожидает несколько вложенных массивов строк.

Спасибо


person zardon    schedule 03.03.2019    source источник
comment
Вставка ваших данных JSON в app.quicktype.io дает вам очень разумное начало моделирования ваших структур Swift.   -  person Gereon    schedule 03.03.2019
comment
Я не знал об этом инструменте, но он выглядит великолепно и высоко ценится   -  person zardon    schedule 03.03.2019


Ответы (2)


Вам просто нужно создать соответствующую структуру и передать ее декодеру:

struct Root: Decodable {
    let people: [String]
    let departments: [[String]]
}

let decoder = JSONDecoder()
do {
    let model = try decoder.decode(Root.self, from: dataResponse)
     print(model.people)      // ["Alice", "Bob"]\n"
     print(model.departments) // [["Accounts", "Sales"]]\n"
} catch {
    print(error) 
}
person Leo Dabus    schedule 03.03.2019
comment
Ах я вижу. это беспокоило меня какое-то время, как декодер работал с несколькими массивами - я могу сделать это для отдельных массивов, но это ценится, и мне, безусловно, нужно освежить свои навыки - person zardon; 03.03.2019

Если вы не хотите создавать структуры (например, вам нужен только фрагмент данных), вот подход, который следует рассмотреть.

let jsonData =  """
{ "people": ["Alice", "Bob"],
"departments": [["Accounts", "Sales"]],
"stores": [["Atlanta", "Denver"]]
}
""".data(using: .utf8)

if let jsonObject = try? JSONSerialization.jsonObject(with: jsonData!, options: []) as? [String: Any] {
    if let people = jsonObject?["people"] as? [String] {
        print(people)
    }
    if let departments = jsonObject?["departments"] as? [[String]] {
        print(departments)
    }
}
person Paul B    schedule 03.03.2019
comment
let jsonData = Data(""" { "people": ["Alice", "Bob"], "departments": [["Accounts", "Sales"]], "stores": [["Atlanta", "Denver"]] } """.utf8). Кстати, ptions: [] можно просто опустить, и для правильного развертывания jsonObject вам нужно добавить круглую скобку if let jsonObject = (try? JSONSerialization.jsonObject(with: jsonData)) as? [String: Any] { - person Leo Dabus; 03.03.2019
comment
Хорошая идея, @Лео. Краткость хороша как бревно, поскольку ясность не страдает. - person Paul B; 04.03.2019