【问题标题】:Parse json inside another json string in swift4在swift4中解析另一个json字符串中的json
【发布时间】:2020-05-19 02:43:08
【问题描述】:

我正在尝试解析 json。但问题是我在里面有另一个 json 字符串。喜欢:

{
    "count": 284,
    "next": "http://X:X:X:X:8080/api/sensor/last5feed?page=2&search=XXXXX",
    "previous": null,
    "results": [
        {
            "id": 571,
            "feed": "{'app_id': 'XXXXX', 'dev_id': 'XXXX', 'hardware_serial': 'XXXXX', 'port': 6, 'counter': 4290, 'payload_raw': 'AQEBIwXsF4IAAAA=', 'payload_fields': {'aamsg_type': 'weather', 'abstatus': 0, 'batteryV': 3.5, 'battery_low': 'no', 'humiP': 60.2, 'tempC': 15.2}, 'metadata': {'time': '2020-01-23T15:09:32.350967362Z', 'frequency': 868.1, 'modulation': 'LORA', 'data_rate': 'SF7BW125', 'airtime': 61696000, 'coding_rate': '4/5', 'gateways': [{'gtw_id': 'XXXXX', 'timestamp': 3227230963, 'time': '2020-01-23T15:09:32.326146Z', 'channel': 0, 'rssi': -98, 'snr': 4.8, 'rf_chain': 1, 'latitude': 57.124737, 'longitude': -2.1646452, 'altitude': 90, 'location_source': 'registry'}]}}",
            "created_at": "2020-01-23T15:09:32.630326Z",
            "sensor": 1
        },
        {
            "id": 569,
            "feed": "{'app_id': 'XXXXXX', 'dev_id': 'XXXX', 'hardware_serial': 'XXXX', 'port': 6, 'counter': 4289, 'payload_raw': 'XXXXX', 'payload_fields': {'aamsg_type': 'weather', 'abstatus': 0, 'batteryV': 3.5, 'battery_low': 'no', 'humiP': 57.6, 'tempC': 16.9}, 'metadata': {'time': '2020-01-23T14:09:32.132070865Z', 'frequency': 867.3, 'modulation': 'LORA', 'data_rate': 'SF7BW125', 'airtime': 61696000, 'coding_rate': '4/5', 'gateways': [{'gtw_id': 'XXXXXX', 'timestamp': 3921981659, 'time': '2020-01-23T14:09:32.104672Z', 'channel': 4, 'rssi': -107, 'snr': 8.2, 'rf_chain': 0, 'latitude': 57.124737, 'longitude': -2.1646452, 'altitude': 90, 'location_source': 'registry'}]}}",
            "created_at": "2020-01-23T14:09:32.448929Z",
            "sensor": 1
        }
}

我得到的值直到饲料。但我无法进一步解析,我的代码是:

if(status_code == 200){
  if let json = response.data {
    do{
      let data = try JSON(data: json)
      let result = data["results"].arrayObject! as NSArray
      let ct = result.count
       if(ct != 0 ) {
       self.noDataFound.isHidden = true
       for i in 0...ct-1 {
          let data = result[i] as? NSDictionary
          let feed = data?.value(forKey: "feed") as? NSString
          let data3 = try JSON(data: feed as! Data) . 
          print(data3)
        }
    }
} catch {} }}

我需要从 feed 中获取 hardware_serial。任何人都可以帮助我在这里做错了什么!谢谢!!!

【问题讨论】:

  • 使用 Codable 解析 json
  • 你能写代码吗!谢谢
  • @Piyush 请检查您的JSON。这不是有效的JSON
  • @Rob 感谢您提供的信息。我已经解决了。

标签: ios json swift parsing


【解决方案1】:
  1. feed 的字符串不是有效的 JSON。您必须用双引号替换单引号。
  2. 从字符串创建一个Data 对象(转换类型不起作用)。
  3. 根据数据创建 JSON 对象。
  4. 获取您需要的值。

旁注:

不要在 Swift 中使用 NS... 集合类型和 NSString

【讨论】:

    【解决方案2】:

    使用 Codable 解析上述 JSON 响应。

    型号:

    struct Root: Codable {
        let count: Int
        let next: String
        let previous: String?
        let results: [Result]
    }
    
    struct Result: Codable {
        let id: Int
        let feed, createdAt: String
        let sensor: Int
    }
    

    解析 JSON data 像这样,

    do {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let response = try decoder.decode(Root.self, from: data)
        print(response)
    } catch {
        print(error)
    }
    

    【讨论】:

      【解决方案3】:

      首先,剥下你想要的那块:

      struct ResultWrapper: Decodable {
          let results: [Result]
      }
      

      然后构建一个自定义解码器来提取格式错误的提要。单引号不是合法的 JSON。作为 hack,以下代码只是用双引号替换所有单引号,但如果有任何嵌入的带引号的单引号,这将不起作用。

      struct Result: Decodable {
          enum CodingKeys: String, CodingKey { case feed }
          let feed: Feed
          init(from decoder: Decoder) throws {
              let container = try decoder.container(keyedBy: CodingKeys.self)
      
              // inner JSON is mal-formed. Have to fix it.
              let feedString = try container.decode(String.self, forKey: .feed)
                  .replacingOccurrences(of: "'", with: "\"")
      
              feed = try JSONDecoder().decode(Feed.self, from: Data(feedString.utf8))
          }
      }
      

      最后,解码 Feed 是机械的,但需要自定义 CodingKeys。为此我推荐quicktype

      // https://app.quicktype.io?share=7O6iNJ3ugXb4mr84TIoG
      struct Feed: Codable {
          var appID, devID, hardwareSerial: String
          var port, counter: Int
          var payloadRaw: String
          var payloadFields: PayloadFields
          var metadata: Metadata
      
          enum CodingKeys: String, CodingKey {
              case appID = "app_id"
              case devID = "dev_id"
              case hardwareSerial = "hardware_serial"
              case port, counter
              case payloadRaw = "payload_raw"
              case payloadFields = "payload_fields"
              case metadata
          }
      }
      
      // MARK: - Metadata
      struct Metadata: Codable {
          var time: String
          var frequency: Double
          var modulation, dataRate: String
          var airtime: Int
          var codingRate: String
          var gateways: [Gateway]
      
          enum CodingKeys: String, CodingKey {
              case time, frequency, modulation
              case dataRate = "data_rate"
              case airtime
              case codingRate = "coding_rate"
              case gateways
          }
      }
      
      // MARK: - Gateway
      struct Gateway: Codable {
          var gtwID: String
          var timestamp: Int
          var time: String
          var channel, rssi: Int
          var snr: Double
          var rfChain: Int
          var latitude, longitude: Double
          var altitude: Int
          var locationSource: String
      
          enum CodingKeys: String, CodingKey {
              case gtwID = "gtw_id"
              case timestamp, time, channel, rssi, snr
              case rfChain = "rf_chain"
              case latitude, longitude, altitude
              case locationSource = "location_source"
          }
      }
      
      // MARK: - PayloadFields
      struct PayloadFields: Codable {
          var aamsgType: String
          var abstatus: Int
          var batteryV: Double
          var batteryLow: String
          var humiP, tempC: Double
      
          enum CodingKeys: String, CodingKey {
              case aamsgType = "aamsg_type"
              case abstatus, batteryV
              case batteryLow = "battery_low"
              case humiP, tempC
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-18
        • 2012-08-06
        • 2011-07-21
        • 2019-05-07
        相关资源
        最近更新 更多