微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何快速解析此JSON格式

如何解决如何快速解析此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将同时处理FloatString,而?将处理null部分。

,

这是一个棘手的问题,需要手动解码。原理是在您希望解码的字段与对象的属性之间定义一个映射,然后根据属性的类型(StringDouble等)尝试解码数据。

第二,由于具有点数组,因此需要某种容器对象来保存该数组,例如:

struct Points {
    var data: [Point] = []
}

首先,您的某些模型属性与数据中的类型不匹配,例如iDString,但是数据具有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 举报,一经查实,本站将立刻删除。