如何解决如何快速解析此JSON格式
我有这种JSON格式:
{
"version":"7.0.19","fields": ["ID","pm","age","pm_0","pm_1","pm_2","pm_3","pm_4","pm_5","pm_6","conf","pm1","pm_10","p1","p2","p3","p4","p5","p6","Humidity","Temperature","Pressure","Elevation","Type","Label","Lat","Lon","Icon","isOwner","Flags","Voc","Ozone1","Adc","CH"],"data":[[20,0.0,1,97,null,1413,"OakDale",40.603077,-111.83612,0.01,1]],"count":11880
}
但是我无法弄清楚如何使用Codable协议来解析json响应。
这将是我想要的模型。
struct Point: Codable {
let pm2: String?
let latitude,longitude: Double?
let temp: String?
let iD: String?
enum CodingKeys: String,CodingKey {
case pm2 = "pm",temp = "Temperature",iD = "ID",latitude = "Lat",longitude = "Lon"
}
}
这是json的URL
https://webbfoot.com/dataa.json
解决方法
您可以使用Codable
对此进行解析:
struct Response: Decodable {
let version: String
let fields: [String]
let data: [[QuantumValue?]]
let count: Int
}
enter code here
enum QuantumValue: Decodable {
case float(Float),string(String)
init(from decoder: Decoder) throws {
if let int = try? decoder.singleValueContainer().decode(Float.self) {
self = .float(float)
return
}
if let string = try? decoder.singleValueContainer().decode(String.self) {
self = .string(string)
return
}
throw QuantumError.missingValue
}
enum QuantumError:Error {
case missingValue
}
}
QuantumValue
将同时处理Float
和String
,而?
将处理null
部分。
这是一个棘手的问题,需要手动解码。原理是在您希望解码的字段与对象的属性之间定义一个映射,然后根据属性的类型(String
,Double
等)尝试解码数据。
第二,由于具有点数组,因此需要某种容器对象来保存该数组,例如:
struct Points {
var data: [Point] = []
}
首先,您的某些模型属性与数据中的类型不匹配,例如iD
是String
,但是数据具有Int
。为简单起见,我将重新定义您的模型以匹配数据
struct Point {
var pm2: Int? = nil
var latitude: Double? = nil
var longitude: Double? = nil
var temp: Int? = nil
var iD: Int? = nil
}
现在,为父容器Points
编写手动解码器:
extension Points: Decodable {
static let mapping: [String: PartialKeyPath<Point>] = [
"pm": \Point.pm2,"Lat": \Point.latitude,"Lon": \Point.longitude,"Temperature": \Point.temp,"ID": \Point.iD
]
enum CodingKeys: CodingKey { case fields,data }
private struct Dummy: Decodable {} // see below why
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let fields = try container.decode([String].self,forKey: .fields)
var data = try container.nestedUnkeyedContainer(forKey: .data)
while !data.isAtEnd {
var row = try data.nestedUnkeyedContainer()
var point = Point()
for field in fields {
let keyPath = Points.mapping[field]
switch keyPath {
case let kp as WritableKeyPath<Point,String?>:
point[keyPath: kp] = try row.decodeIfPresent(String.self)
case let kp as WritableKeyPath<Point,Int?>:
point[keyPath: kp] = try row.decodeIfPresent(Int.self)
case let kp as WritableKeyPath<Point,Double?>:
point[keyPath: kp] = try row.decodeIfPresent(Double.self)
default:
// this is a hack to skip this value
let _ = try? row.decode(Dummy.self)
}
}
self.data.append(point)
}
}
}
一旦有了,就可以像这样解码JSON:
let points = try JSONDecoder().decode(Points.self,from: jsonData)
let firstPoint = points.data[0]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。