jsonswiftdeserializationjson-deserialization

How to send jSON in a url and later on deserialize it and format it in swift


so am sending a request from my swift app using ASWebAuthenticationSession to this link ->

https://webcode.tools/generators/html/hyperlink

afterwards, on opening the website, I enter my callback URL in the URL field provided on the site -> this is the callback URL am sending -

myApp://home/redirect?status=Wow-2023&code=200&data={\n \"name\": \"ios\",\n \"age\": 10,\n }

so in the status I had to send a string, in the code I had to send an Int, and in the data I had to send a JSON String

and then I click on " Click Here " under Preview section of the website and i have added the URLScheme so my app opens up and i receive the callback URL but now it's changed . the URL returned to me is -

myApp://home/redirect?status=Wow-2023&code=200&data=%7B%5Cn%20%5C

now i have to show the status the code and the json deserialized and formatted in an alert box, the status and code is done but i don't get the JSON object out from this string of data, i have tried all this -

func nsdataToJSON(data: Data) -> AnyObject? {
    do {
        return try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as AnyObject
    } catch let myJSONError {
        print(myJSONError)
    }
    return nil
}

this returns nil

            guard let decoded = try? JSONDecoder().decode(Person.self, from: Data(dataString.utf8)) else {
            print("AD:: we returned")
            return

        }

this also returns and I don't get any value what am I doing wrong here please help, am I not sending the right JSON in the URL field on the website?


Solution

  • I don't think passing JSON data in query parameters is a good idea, and it may not work, especially if your JSON data is very long.

    In order to get it to work you will need to apply the correct encoding to the query parameters. By far the easiest and safest way to do that is to use an instance of URLComponents. Try using code like this to build your URL:

    var compnonents = URLComponents()
    guard let url = URL(string: "myApp://home/redirect"),
          var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
        fatalError("splat!")
    }
    let query1 = URLQueryItem(name: "Status", value: "Wow")
    let query2 = URLQueryItem(name: "code", value: "200")
    let query3 = URLQueryItem(name: "data", value: "{\n \"name\": \"ios\",\n \"age\": 10,\n }")
    components.queryItems = [query1, query2, query3]
    
    if let urlString = components.string {
        print("URL string = '\(urlString)'")
    } else {
        print("Can't get string from URL")
    }
    
    if let queryItems = components.queryItems {
        print("\n---> Query items from components <---\n")
        for (index, queryItem) in queryItems.enumerated() {
            print("queryItem[\(index)] :")
            print("'\(queryItem)'")
        }
    }
    
    

    That generates this output:

    URL string = 
    'myApp://home/redirect?Status=Wow&code=200&data=%7B%0A%20%22name%22:%20%22ios%22,%0A%20%22age%22:%2010,%0A%20%7D'
    
    ---> Query items from components <---
    
    queryItem[0] :
    'Status=Wow'
    queryItem[1] :
    'code=200'
    queryItem[2] :
    'data={
     "name": "ios",
     "age": 10,
     }'
    

    Note how the URLComponents applies the appropriate escaping to the contents of your "data" query parameter when building an URL string, and also returns an un-escaped JSON string when you fetch the query parameters.

    In your app when you parse the incoming URL you should use the above approach to extract the query parameters.