Unable to Parse JSON Files on Swift3

Asked 2 years ago, Updated 2 years ago, 104 views

I'm getting JSON from my API server and trying to log it.

let json:NSDictionary=try JSONSerialization.jsonObject(with:data!,options:.allowFragments)as!NSDictionary

in the section
The data couldn't be read because it is not in the correct format.

I get an error saying, but what is the cause of> From the contents of the session risp variable, I think the API access was successful with status code=200

SWIFT Code

func someTask(){
        let url = URL (string: "My API Address")!
        let session = URLSession(configuration:URLSessionConfiguration.default)
        let task = session.dataTask(with:url, completionHandler:{
            (data, resp, error) in

            if error!=nil{
                letstr=NSString(data:data!, encoding:String.Encoding.utf8.rawValue)
                print(str!)

                print(error!.localizedDescription)
                return
            }

            do{

                let json:NSDictionary=try JSONSERIALIZATION.jsonObject(with:data!,options:.allowFragments)as!NSDictionary

                print(json["a"]???"a:none")
                print(json["b"]???"b:none")

            } catchlet error as NSError {
                print(error.localizedDescription)
            }

        })
        task.resume()
    }

Code of your own API

<html>
<head>
</head>
<body>

<?php

$returnValue=array("a"=>1,"b"=>2);
echo json_encode($returnValue);

?>

</body>
</html>

When I actually accessed my API, I found it.

swift swift3

2022-09-30 21:19

1 Answers

Your homegrown API code returns a byte string equivalent to the following string:

<html>
<head>
</head>
<body>

{"a":1, "b":2}

</body>
</html>

JSON responses buried in HTML tags like this cannot be parsed in JSONSERIALIZATION.

Try changing the server-side code as follows:

<?php

$returnValue=array("a"=>1,"b"=>2);
echo json_encode($returnValue);

I would like to recommend some modifications to Swift's code, so I will list them in bullet points.

(There should be no fatal impact on this issue, so you can ignore the following.)

  • data in case of error could be nil, so data! could crash the app
  • You do not need to use NSString to string a response in case of an error
  • str! is also dangerous

    because the response to the error may not be interpreted by UTF-8
    iflet data=data{
                let str = String (data:data, encoding: .utf8)
                print(str??"data not in UTF-8")
            } else{
                print("data is nil")
            }
    
  • If you expect the result to always be a JSON object (Dictionary on Swift side), you do not need options:.allowFragments

  • Swift3 makes it easier to get into the habit of using Swift's Dictionary (or Array) than using NSDictionary (or Array).
  • as! causes the app to crash when a non-JSON object response arrives

    iflet json=try JSONSERIALIZATION.jsonObject(with:data!)as?[String:Any]{
                print(json["a"]???"a:none")
                print(json["b"]???"b:none")
            } else{
                print ("invalid JSON")
            }
    

str! is also dangerous

because the response to the error may not be interpreted by UTF-8
iflet data=data{
            let str = String (data:data, encoding: .utf8)
            print(str??"data not in UTF-8")
        } else{
            print("data is nil")
        }

If you expect the result to be a JSON object (Dictionary on Swift side), you do not need options:.allowFragments

as! causes the app to crash when a non-JSON object response arrives

iflet json=try JSONSERIALIZATION.jsonObject(with:data!)as?[String:Any]{
            print(json["a"]???"a:none")
            print(json["b"]???"b:none")
        } else{
            print ("invalid JSON")
        }


2022-09-30 21:19

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.