1

I am trying to parse the JSON which is getting from server response. But I'm unable to parse, the JSON getting error.

This is my code:

let data = Data(message.utf8)

do {
    let jsonDict = try JSONSerialization.jsonObject(with: data,options: .allowFragments) as? NSDictionary
    print(jsonDict)
} catch let error as NSError { 
    print("Failed to load: \(error.localizedDescription)")
}

This response I'm getting from server:

{
  "requestId": "123",
  "success": true,
  "body": {
    "expirydate": "10/11/2020",
    "gsm": "9988776655",
    "pass": "123456",
    "registerdate": "10/10/2020",
    "type": "paid",
    "typeofsubscription": "30days",
    "username": "aryan"
  }
}

Please help me out. Thank you

gcharita
  • 7,729
  • 3
  • 20
  • 37
  • Print only the `error` instance and delete `localizedDescription` as well as the type cast to `NSError`. Probably you will get a more meaningful error message. And delete also `.allowFragments` which is pointless if the expected type is a collection type. And don’t use `NSDictionary` in Swift. Use native types. – vadian Oct 10 '20 at 10:05
  • After printing the error only getting this error Error Domain=NSCocoaErrorDomain Code=3840 "Garbage at end." UserInfo={NSDebugDescription=Garbage at end.} – Anand Vishwakarma Oct 10 '20 at 10:46

2 Answers2

0

Actually there's no error in your code. You can run this code below. If anything wrong, please share details. i.e your api calling or anything

        let someString = """
{ "requestId": "123", "success": true, "body": { "expirydate": "10/11/2020", "gsm": "9988776655", "pass": "123456", "registerdate": "10/10/2020", "type": "paid", "typeofsubscription": "30days", "username": "aryan" } }
"""
        let data = Data(someString.utf8)
        do {
            let jsonDict = try JSONSerialization.jsonObject(with: data,options: .allowFragments) as? NSDictionary
            print(jsonDict)
            print(jsonDict?["requestId"])
        } catch let error {
            print("\(error.localizedDescription)")
        }

Output:

Optional({
    body =     {
        expirydate = "10/11/2020";
        gsm = 9988776655;
        pass = 123456;
        registerdate = "10/10/2020";
        type = paid;
        typeofsubscription = 30days;
        username = aryan;
    };
    requestId = 123;
    success = 1;
})
Optional(123)
AMIT
  • 906
  • 1
  • 8
  • 20
  • I'm getting json in log but when put the break in my code im getting string like this "{\"requestId\":\"123\",\"success\":true,\"body\":{\"expirydate\":\"10-11-2020\",\"gsm\":\"5566778833\",\"pass\":\"123456\",\"registerdate\":\"10-10-2020\",\"type\":\"paid\",\"typeofsubscription\":\"30days\",\"username\":\"alice\"}}\r\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 – Anand Vishwakarma Oct 10 '20 at 10:16
  • please give your message log – AMIT Oct 10 '20 at 10:27
  • This actual json is {"requestId":"123","success":true,"body":{"expirydate":"10-11-2020","gsm":"5566778833","pass":"123456","registerdate":"10-10-2020","type":"paid","typeofsubscription":"30days","username":"alice"}} – Anand Vishwakarma Oct 10 '20 at 10:41
  • but I don't know how this json string converted like this {\"requestId\":\"123\",\"success\":true,\"body\":{\"expirydate\":\"10-11-2020\",\"gsm\":\"5566778833\",\"pass\":\"123456\",\"registerdate\":\"10-10-2020\",\"type\":\"paid\",\"typeofsubscription\":\"30days\",\"username\":\"alice\"}}\r\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 – Anand Vishwakarma Oct 10 '20 at 10:42
  • check this post https://stackoverflow.com/questions/50365531/serialize-json-string-that-contains-escaped-backslash-and-double-quote-swift-r let me know if issue still remains. – Dev JD Oct 10 '20 at 10:48
  • let jsonObject: [String: Any?] = [ "requestId":"123", "method":"read", "username":"alice", "pass":"123456", "body":nil ] do { let jsonData = try JSONSerialization.data(withJSONObject: jsonObject, options: []) let jsonString = String(data: jsonData, encoding: .utf8) ?? "" send(message: jsonString) } catch let myJSONError { debugPrint(myJSONError) } Is this right? – Anand Vishwakarma Oct 10 '20 at 11:27
  • Give your response data into JSONSerialization. Don't convert it as string – AMIT Oct 10 '20 at 15:05
0

Never print error.localizedDescription) in a JSONSerialization or JSONDecoder context. Print always just the error instance.

The error

Erro Domain=NSCocoaErrorDomain Code=3840 "Garbage at end." UserInfo={NSDebugDescription=Garbage at end.

is pretty clear: There are control characters and zero bytes at the end of the string.

A possible solution to remove the zero bytes is

var data = Data(message.utf8)
data.removeAll{ $0 == 0 }
do {
    let jsonDict = try JSONSerialization.jsonObject(with: data) as? [String:Any]
    print(jsonDict)
} catch  {
    print("Failed to load: \(error)")
}

However a better solution is to collect the garbage on the server.

Notes:

  • .allowFragments is pointless if the expected type is a collection type
  • Don't use NS... collection types in Swift at all. Use native types.
vadian
  • 274,689
  • 30
  • 353
  • 361