JSON backslash encoding

I use Alamofire and SwiftyJSOn to parse JSON output. It works very well, however some sites give json with shielded output. I am using Alamofire as shown below.

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

The site gives me a JSON result with an escaped string, so SwiftyJSON cannot decode it. How to convert below

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

to something like

 { "d": { "UniqeView": { "ArrivalDate": null, "ArrivalUnitId": null, "DeliveryCityName": null, "DeliveryTownName": null }, "ErrorMessage": null, "Message": null, "IsFound": false, "IsSuccess": true } } 
+9
swift alamofire swifty-json
source share
6 answers
 // 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 } } } } 

I assume that you should decode twice: the fairing object and its contents.

+6
source share

@Ericd's comments helped me solve this problem. I accepted his answer to this question. Since I use Alamofire for asynchronous operation and SwiftyJSON, I could not use its code. Here is the code with Alamofire and 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!) 
+5
source share

Many people have problems with the differences between what they get and what their system prints. So, the first step - you need to find out exactly what you get, and whether these escape characters are just a print artifact.

If this is what you are actually getting, the server sent you a dictionary with one d key and a string, and the string contains serialized data. In this case, convert the string to NSData and paste it into NSJSONSerialization, which will turn it into the required dictionary. This is a pretty dumb way to pass JSON data, but it does.

+2
source share

Here is another approach for Swift 4 - Using Codable

This was the JSON I received:

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

The backslash JSON part is equal to this:

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

And that was the code I used:

 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 } } 

And this is a trick:

 emeter = try JSONDecoder().decode(Emeter.self, from: Data(dataString.utf8)) 
+1
source share

I use some custom functions to do this work:

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

I hope this helps;)

0
source share

For too long I tried to figure out the same problem. This is how I solved it.

Do I have a network manager that returns [Any] when called?

I go through each entry, converting it to JSON, but in this case it does not recognize the built-in dictionary structure.

So, I pull out rawString and then use parsing. It recognizes a dictionary.

From there, you can use it the way you want. In my example, I am passing data to a data model (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 }) 
0
source share

All Articles