带反斜杠的JSON编码

时间:2015-03-23 16:00:02

标签: swift alamofire swifty-json

我使用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
       }
    }

6 个答案:

答案 0 :(得分: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
            }

        }
    }
}

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

答案 1 :(得分: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!)

答案 2 :(得分:2)

很多人在区分他们得到的东西和他们的系统打印方面存在问题。因此,第一步是你需要找出你接收的确切内容,以及这些转义字符是否只是你打印的人工制品。

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

答案 3 :(得分:0)

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

import Foundation

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

我希望它有所帮助;)

答案 4 :(得分:0)

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

我有一个网络管理员,在调用时,返回[Any]的响应?

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

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

从那里你应该能够像你一样使用它。在我的示例中,我将数据传递给数据模型(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
        })

答案 5 :(得分:0)

这是Swift 4的另一种方法-使用可编码

这是我收到的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
    }
}