Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialize JSON string that contains escaped (backslash and double quote) Swift return Badly formed object

I have response string from the backend like this:

{
    "status": "success",
    "data": "{\"name\":\"asd\",\"address\":\"Street 1st\"}"
}

I think the problem was because the double quote (") in the data String. When I remove the double quote, the serialization was success. But the response is from backend and I have to deal with it.

Anyone can solve this problem?

Thank you.

Here is the playground code.

import Foundation
var jsonStr = """
{
"status": "success",
"data": "{\"name\":\"asd\",\"address\":\"Street 1st\"}"
}
"""
let data = jsonStr.data(using: .utf8)
if let d = data {
    do {
        let o = try JSONSerialization.jsonObject(with: d)
        print(o)
    } catch let e {
        print(e)
    }
} else {
    print("DATA conversion ERROR")
}
like image 664
Jefferson Setiawan Avatar asked May 16 '18 08:05

Jefferson Setiawan


People also ask

How do you escape a double quote in JSON?

if you want to escape double quote in JSON use \\ to escape it.

How do you escape a single quote in JSON?

In JSON, you don't need to escape single quotes inside a value that is enclosed with double-quotes. In the case that you have double quotes as part of a value (that is enclosed with double quotes) then you would need to escape them.

What are backslashes in JSON?

Those backslashes are escape characters. They are escaping the special characters inside of the string associated with JSON response. You have to use JSON. parse to parse that JSON string into a JSON object.

Can I use single quote in JSON?

Strings in JSON are specified using double quotes, i.e., " . If the strings are enclosed using single quotes, then the JSON is an invalid JSON .


1 Answers

First of all if you wrap the JSON in the literal string syntax of Swift 4 you have to escape the backslashes.

let jsonStr = """
{
"status": "success",
"data": "{\\"name\\":\\"asd\\",\\"address\\":\\"Street 1st\\"}"
}
"""

You got nested JSON. The value for key data is another JSON string which must be deserialized separately

let jsonData = Data(jsonStr.utf8)

do {
    if let object = try JSONSerialization.jsonObject(with: jsonData) as? [String:String] {
        print(object)
        if let dataString = object["data"] as? String {
            let dataStringData = Data(dataString.utf8)
            let dataObject = try JSONSerialization.jsonObject(with: dataStringData) as? [String:String]
            print(dataObject)
        }
    }
} catch {
    print(error)
}

Or – with a bit more effort but – much more comfortable with the (De)Codable protocol

struct Response : Decodable {

    private enum CodingKeys : String, CodingKey { case status, data }

    let status : String
    let person : Person

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        status = try container.decode(String.self, forKey: .status)
        let dataString = try container.decode(String.self, forKey: .data)
        person = try JSONDecoder().decode(Person.self, from: Data(dataString.utf8))
    }
}

struct Person : Decodable {
    let name, address : String
}

let jsonStr = """
{
"status": "success",
"data": "{\\"name\\":\\"asd\\",\\"address\\":\\"Street 1st\\"}"
}
"""
let jsonData = Data(jsonStr.utf8)

do {
    let result = try JSONDecoder().decode(Response.self, from: jsonData)
    print(result)
} catch {
    print(error)
}
like image 137
vadian Avatar answered Oct 16 '22 03:10

vadian