После отслеживания вашей проблемы, я понял, что есть пара проблем, в первую очередь:
Вы НЕ объявляете дополнительные опции:
основываясь на прикрепленном json, кажется, что существуют некоторые свойства, которые не существуют всегда, например:
status
=> VportSensor
. temperature
=> Measurement
. temperature
=> VportSensor
. temperature
=> setpoints
.
вам потребуется , убедитесь, что объявили любое свойство, которое может быть не получено как необязательное.
Также, Реализация кодируемых структур :
реализованные структуры кажутся не типичными для структуры ответа json, убедитесь, что ваши кодируемые структуры сопоставлены с полученной структурой json.
Обратите внимание, что:
lastUpdate
и description
не используются в VportSensor
. - Исходя из моего ответа, нет необходимости
TemperatureSensor
...
Tip:
Когда дело доходит до работы с датами (например, ts
), вы должны объявить его непосредственно как Date
вместо String
и затем установить удобное dateDecodingStrategy
.В вашем случае, это должен быть пользовательский, вы можете найти, как это сделать, в этом ответе .
Реализация:
На основе приведенного выше описанияесть полная реализация:
struct Main: Codable {
let type: String
let ts: Date
let source: String
let unit: Unit
let measurement: Measurement
}
struct Unit: Codable {
var number: String
}
struct Measurement: Codable {
let ts: String
let sensors: [VportSensor]
let sensor: VportSensor
let temperature: Double?
}
struct LastTemperatureResponseElement: Codable {
let measurement: Measurement
}
struct VportSensor: Codable {
//let lastUpdate: String!
//let description: String
let address: String
let name: String?
let status: String?
let temperature: Double?
let setpoints: [Setpoint]?
}
struct Setpoint: Codable {
let address: String
let name: String
}
// this part from the mentioned answer for creating custom `dateDecodingStrategy`:
enum DateError: String, Error {
case invalidDate
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
let container = try decoder.singleValueContainer()
let dateStr = try container.decode(String.self)
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
if let date = formatter.date(from: dateStr) {
return date
}
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
if let date = formatter.date(from: dateStr) {
return date
}
throw DateError.invalidDate
})
Вывод:
let decoder = JSONDecoder()
do {
let temp = try decoder.decode([Main].self, from: json)
// here we go, `temp` is an array of main object of the json
} catch {
print(error)
}
Если вам интересно, что такое json
в
let temp = try decoder.decode([Main].self, from: json)
Я просто взял прикрепленный ответ json и добавил его в Data
Объект:
let json = """
[
{
"type": "temperatures",
"ts": "2017-11-08T16:43:59.558Z",
"source": "thermo-king",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2017-11-08T16:43:18.000Z",
"sensors": [
{
"address": "t1",
"description": "LFTest1",
"setpoints": [
{
"address": "s1",
"name": "LFSTest1"
}
]
},
{
"address": "t2",
"description": "LFTest2",
"setpoints": [
{
"address": "s2",
"name": "LFSTest2"
}
]
},
{
"address": "t3",
"description": "LFTest3",
"setpoints": [
{
"address": "s3",
"name": "LFSTest3"
}
]
},
{
"address": "t4",
"description": "LFTest4"
},
{
"address": "t5",
"description": "LFTest5"
},
{
"address": "t6",
"description": "LFTest6"
}
],
"sensor": {
"address": "t1",
"name": "LFTest1"
},
"setpoints": [
{
"address": "s1",
"name": "LFSTest1"
}
]
}
},
{
"type": "temperatures",
"ts": "2018-06-07T07:05:38.962Z",
"source": "1-wire",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2018-06-07T07:05:31.000Z",
"sensors": [
{
"address": "2839A5B104000004",
"description": "1-wire #1",
"status": "ok",
"temperature": 24.8
},
{
"address": "28EFBAB104000061",
"description": "1-wire #3",
"status": "ok",
"temperature": 24.5
},
{
"address": "2845F6B504000034",
"description": "1-wire #2",
"status": "ok",
"temperature": 24.5
}
],
"sensor": {
"address": "2839A5B104000004",
"name": "1-wire #1",
"status": "ok"
},
"temperature": 24.8
}
},
{
"type": "temperatures",
"ts": "2018-06-07T07:11:50.030Z",
"source": "vport",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2018-06-07T07:11:47.000Z",
"sensors": [
{
"address": "1036040010",
"description": "Vport 1-wire",
"status": "high",
"temperature": 26
}
],
"sensor": {
"address": "1036040010",
"name": "Vport 1-wire",
"status": "high"
},
"temperature": 26
}
}
]
""".data(using: .utf8)!