10

我正在使用 Alamofire 和 SwiftyJSOn 来解析 JSON 输出。它工作得很好,但是有些网站提供带有转义输出的 json。我像下面这样使用 Alamofire

    Alamofire.request(.POST, url, parameters: param, encoding: .JSON)
        .responseJSON { (req, res, json, error) in
         var json = JSON(json!)

站点给了我带有转义字符串的 JSON 结果,因此 SwiftyJSON 无法对其进行解码。如何在下面转换

{
    "d": "{\"UniqeView\":{\"ArrivalDate\":null,\"ArrivalUnitId\":null,\"DeliveryCityName\":null,\"DeliveryTownName\":null},\"ErrorMessage\":null,\"Message\":null,\"IsFound\":false,\"IsSuccess\":true}"
}

类似于

{
       "d": {
          "UniqeView": {
             "ArrivalDate": null,
             "ArrivalUnitId": null,
             "DeliveryCityName": null,
             "DeliveryTownName": null
          },
          "ErrorMessage": null,
          "Message": null,
          "IsFound": false,
          "IsSuccess": true
       }
    }
4

6 回答 6

6
// This Dropbox url is a link to your JSON
// I'm using NSData because testing in Playground
if let data = NSData(contentsOfURL: NSURL(string: "https://www.dropbox.com/s/9ycsy0pq2iwgy0e/test.json?dl=1")!) {

    var error: NSError?
    var response: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error)
    if let dict = response as? NSDictionary {
        if let key = dict["d"] as? String {

            let strData = key.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
            var error: NSError?
            var response: AnyObject? = NSJSONSerialization.JSONObjectWithData(strData!, options: NSJSONReadingOptions.allZeros, error: &error)

            if let decoded = response as? NSDictionary {
                println(decoded["IsSuccess"]!)   // => 1
            }

        }
    }
}

我猜你必须解码两次:包装对象及其内容。

于 2015-03-23T16:42:36.893 回答
5

@ericd 评论帮助我解决了这个问题。我接受了他对这个问题的回答。由于我使用 Alamofire 进行异步操作和 SwiftyJSON,我无法使用他的代码。这是 Alamofire 和 SwiftyJSON 的代码。

Alamofire.request(.POST, url, parameters: param, encoding: .JSON)
   .responseJSON { (req, res, json, error) in
    if(error != nil) {
        NSLog("Error: \(error)")
        failure(res, json, error)
    }
    else {

        var jsond = JSON(json!)
        var data = jsond["d"].stringValue.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
        jsond = JSON(data: data!)
于 2015-03-24T10:19:18.857 回答
2

很多人在区分他们得到的东西和他们的系统打印的东西之间存在问题。所以第一步是你需要找出你到底收到了什么,以及这些转义字符是否只是你打印的产物。

如果这是您实际收到的,那么服务器已经向您发送了一个带有单个键“d”和一个字符串的字典,并且该字符串包含序列化数据。在这种情况下,将字符串转换为 NSData 并将其推入 NSJSONSerialization,这会将其转换为您想要的字典。这是传输 JSON 数据的一种相当愚蠢的方式,但它确实发生了。

于 2015-03-23T16:31:47.637 回答
1

这是 Swift 4 的另一种方法 -使用 Codable

这是我收到的 json:

{
    "error_code": 0,
    "result": {
        "responseData": "{\"emeter\":{\"get_realtime\":{\"voltage_mv\":237846,\"current_ma\":81,\"power_mw\":7428,\"total_wh\":1920,\"err_code\":0}}}"
    }
} 

带有反斜杠的 JSON 部分等于:

{
    "emeter": {
        "get_realtime": {
            "voltage_mv": 237846,
            "current_ma": 81,
            "power_mw": 7428,
            "total_wh":19201,
            "err_code":0
        }
    }
}

这是我使用的代码:

import Foundation

class RealtimeEnergy: Codable {
    let errorCode: Int
    let result: ResultRealtimeEnergy?
    let msg: String?

    enum CodingKeys: String, CodingKey {
        case errorCode = "error_code"
        case result, msg
    }

    init(errorCode: Int, result: ResultRealtimeEnergy?, msg: String?) {
        self.errorCode = errorCode
        self.result = result
        self.msg = msg
    }
}

class ResultRealtimeEnergy: Codable {

    let responseData: String
    var emeter: Emeter

    enum CodingKeys: String, CodingKey {
        case responseData
    }

    required init(from decoder: Decoder) throws {

        let container = try decoder.container(keyedBy: CodingKeys.self)
        responseData = try container.decode(String.self, forKey: .responseData)
        let dataString = try container.decode(String.self, forKey: .responseData)
        emeter = try JSONDecoder().decode(Emeter.self, from: Data(dataString.utf8))
    }
}



class Emeter: Codable {
    let emeter: EmeterClass

    init(emeter: EmeterClass) {
        self.emeter = emeter
    }
}

class EmeterClass: Codable {
    let getRealtime: GetRealtime

    enum CodingKeys: String, CodingKey {
        case getRealtime = "get_realtime"
    }

    init(getRealtime: GetRealtime) {
        self.getRealtime = getRealtime
    }
}

class GetRealtime: Codable {
    let voltageMv, currentMa, powerMw, totalWh: Int
    let errCode: Int

    enum CodingKeys: String, CodingKey {
        case voltageMv = "voltage_mv"
        case currentMa = "current_ma"
        case powerMw = "power_mw"
        case totalWh = "total_wh"
        case errCode = "err_code"
    }

    init(voltageMv: Int, currentMa: Int, powerMw: Int, totalWh: Int, errCode: Int) {
        self.voltageMv = voltageMv
        self.currentMa = currentMa
        self.powerMw = powerMw
        self.totalWh = totalWh
        self.errCode = errCode
    }
}

这就是诀窍:

emeter = try JSONDecoder().decode(Emeter.self, from: Data(dataString.utf8))
于 2019-05-01T12:35:38.847 回答
0

我使用一些自定义函数来完成这项工作:

import Foundation

func unescapeString(string: String) -> String {
    return string.stringByReplacingOccurrencesOfString("\"", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
}

我希望它有帮助;)

于 2015-03-23T16:25:50.167 回答
0

我花了太长时间试图找出同样的问题。这是我解决它的方法。

我有一个网络管理器,当被调用时,它会返回 [Any] 的响应?

我遍历每条记录,将其转换为 JSON,但在这种情况下无法识别固有的字典结构。

所以我采摘 rawString 然后使用解析。这确实识别字典。

从那里你应该能够像你一样使用它。在我的示例中,我将数据传递给数据模型(MyApi),

networkManager .requestResource(withUrl: urlPath, andParams: params, 
successHandler: { (response: [Any]?) in

            if let rawResponse = response {

                let mutableArray = NSMutableArray()

                for item in rawResponse {

                    let jsonData = JSON(item)
                    guard let rawString = jsonData.rawString() else {
                        return
                    }

                    let parsedData = JSON.parse(rawString)

                let typedResponse = MyApi(json: parsedData)
                    mutableArray.add(typedResponse)
                }

                let array = mutableArray.copy() as! [MyApi]
                //do something with array

            } else {
                let error = NSError .init(domain: "MyApi", code: 100, userInfo: nil)
                //log error
            }

        }, failureHandler: { (response: [Any]?) in

            let error = NSError .init(domain: "MyApi", code: 101, userInfo: nil)
            //log error
        })
于 2017-07-09T21:40:26.397 回答