Используйте Swift Decoder для извлечения атрибутов из массива JSON

У меня есть массив JSON, созданный с помощью этого вызова:

guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [Any] else {
    print("This is not JSON!!!")
    return
}

Я пытаюсь получить элементы из объектов JSON в массиве, чтобы отобразить их, используя следующий код:

struct sWidget: Codable{
    var createdBy: String
    var createdDate: Date
    var status: String
    var widgetNumber: String
    var updatedBy: String
    var updatedDate: Date
}


do {
    let decoder = JSONDecoder()
    for (index, value) in json.enumerated() {
        let currentWidget = try decoder.decode(sWidget.self, from: json[index] as! Data)
        let currentNum = currentWidget.widgetNumber
            //print(currentNum)
        widgetNums.append(currentNum)
    }
}
catch {
    print("decoding error")
}

Код компилируется, но когда я его запускаю, я получаю эту ошибку на выходе:

Could not cast value of type '__NSDictionaryM' (0x1063c34f8) to 'NSData' (0x1063c1090). 2018-08-09 09:41:02.666713-0500 TruckMeterLogScanner[14259:1223764] Could not cast value of type '__NSDictionaryM' (0x1063c34f8) to 'NSData' (0x1063c1090).

Я все еще продолжаю расследование, но любые советы были бы полезны.

Это нормально, потому что json уже является массивом Dictionary / Array / String / Int, уже сериализованным, поэтому внутри него не будет объекта Data, поэтому json[index] не является объектом (NS)Data, поэтому json[index] as! Data выйдет из строя. Если вы просто заинтересованы в получении чисел, отправьте после let widgets = jsonDecoder.decode([sWidget].self, data: content), выполните widgetNums.append (contentsOf: widgets.map {$ 0.widgetNumber} `.

Larme 09.08.2018 17:01
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
1
146
2

Ответы 2

Вы пробовали получать объекты, как указано выше? Потому что я вижу, что вы используете Codable. На самом деле выборка очень проста.

let yourObjectArray = JSONDecoder().decode([sWidget].self, data: json as! Data)

Может быть, эта строка может быть ошибочной, но вы можете получить их одной строкой.

Я пробовал использовать этот код, но получаю предупреждение о том, что приведение из [Any] к несвязанному типу «Данные» всегда терпит неудачу.

Jacobi 09.08.2018 17:05

let yourObjectArray = try JSONDecoder (). decode ([sTruck] .self, from: json as! Data)

Jacobi 09.08.2018 17:06

@Jacobi, вы используете Alamofire для получения данных? Это пример функции загрузки с помощью Alamofire. Я бы хотел, чтобы это вам помогло. gist.github.com/Cemoo/3ed4f5a3eff11082b064e745d3ef6b35

Cemal BAYRI 10.08.2018 09:49

Расширение ответа @Cemal BAYRI:

JSONDecoder() бросает, поэтому обязательно используйте try? или try (не забудьте do-catch с try)

guard let data = content as? Data else {
   return [sWidget]()
}

let jsonDecoder = JSONDecoder()

1. пытаться?

let yourObjectArray = try? jsonDecoder.decode([sWidget].self, data: data)

2. пытаться

do {
  let yourObjectArray = try jsonDecoder.decode([sWidget].self, data: data)
} catch let error {
}  

Примечание: Вам нужно будет позаботиться о форматировании Data и Date. Ниже приведен пример для Date:

jsonDecoder.dateDecodingStrategy = .iso8601

Вы также можете проверить это здесь

пусть данные = json как? Данные не заполняют данные. После выполнения этой строки кода он по-прежнему равен нулю.

Jacobi 09.08.2018 17:43

Здесь json - это имя переменной, содержащей данные. Судя по вашему вопросу, это будет content.

Nasir 09.08.2018 17:50

контент уже является типом данных. Я заменяю вызов сериализации вызовом декодирования?

Jacobi 09.08.2018 17:54

да. Декодер заменяет сериализацию плюс все другие шаги, необходимые для преобразования json в модели.

Nasir 09.08.2018 17:58

Другие вопросы по теме