Decoding JSON

Hi there,

I am trying to decode JSON response that's being sent by ServiceNow but I am getting an error -

"keyNotFound(CodingKeys(stringValue: "short_description", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: "short_description", intValue: nil) ("short_description").", underlyingError: nil))"

JSON response sent by ServiceNow:

{

       "result": {

         "short_description": "broken door",

         "due_date": "2022-04-01",

         "sys_mod_count": "0",

         "inspector": "",

         "sys_updated_on": "2022-03-06 05:17:59",

         "priority": "low",

         "sys_tags": "",

         "number": "SAFT0001034",

         "sys_id": "e9823a3d07024119898908080ed0ce",

         "sys_updated_by": "admin",

         "opened_by": {

           "link": "https://dev******.service-now.com/api/now/table/sys_user/TOP2",

           "value": "TOP2"

         },

         "sys_created_on": "2022-03-06 05:17:59",

         "location": {

           "link": "https://dev******.service-now.com/api/now/table/cmn_location/2e3c49b037d0200044e0829849df9",

           "value": "2e3c49b037d0200044e0b8493849e5df9"

         },

         "state": "new",

         "category": "big",

         "sys_created_by": "admin",

         "assigned_to": ""

       }

     }

Here is the code:

struct Opened_By: Codable  {

var link: String = ""

var value: String = ""

 }

struct Location: Codable {

var link: String = ""

var value: String = ""

}

struct Response: Codable {

        var short_description: String = ""

        var due_date: String = ""

        var sys_mod_count: String = ""

        var inspector: String = ""

        var sys_updated_on: String = ""

        var priority: String = ""

        var sys_tags: String = ""

        var number: String = ""

        var sys_id: String = ""

        var sys_updated_by: String = ""

        var opened_by: Opened_By

        var sys_created_on: String = ""

        var    location: Location

        var state: String = ""

        var category: String = ""

        var sys_created_by: String = ""

        var assigned_to: String = ""
}

Any help in decoding the response will be greatly appreciated.

Many thanks :)

Answered by Claude31 in 706623022

There a few things I don't understand in your code.

What doc you do with this dictionary ?

            let dictionary = try   JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String:Any]        

You have a result keyword in your JSON file, but I do not see it in the servicenowResponse

You should either declare it in servicenowResponse

struct SomeResponse: Codable {
        var short_description: String = ""
// etc …
}

struct ServiceNowResponse: Codable {
        var someResponse : SomeResponse()
}

or isolate what is inside result for decoder.

Note: struct name should start with upperCase and be CamelCase : ServiceNowResponse

Could you show the complete code and where you get the error message. How do you get JSON data ?

Sorry here is the code

import UIKit

struct servicenowRequest: Codable

{
    var opened_by: String = "YR"
    var category: String = "Big"
    var location: String = "iOS"
    var due_date: String = "4/1/2022"
    var short_description: String = "broken door"
}

struct Opened_By: Codable  {
    var link: String = ""
    var value: String = ""
}

struct Location: Codable {
    var link: String = ""
    var value: String = ""
}

struct servicenowResponse: Codable

{
        var short_description: String = ""
        var due_date: String = ""
        var sys_mod_count: String = ""
        var inspector: String = ""
        var sys_updated_on: String = ""
        var priority: String = ""
        var sys_tags: String = ""
        var number: String = ""
        var sys_id: String = ""
        var sys_updated_by: String = ""
        var opened_by: Opened_By
        var sys_created_on: String = ""
        var location: Location
        var state: String = ""
        var category: String = ""
        var sys_created_by: String = ""
        var assigned_to: String = ""
}   

/* Response sent by ServiceNow API

     {
       "result": {
         "short_description": "broken door",
         "due_date": "2022-04-01",
         "sys_mod_count": "0",
         "inspector": "",
         "sys_updated_on": "2022-03-06 05:17:59",
         "priority": "low",
         "sys_tags": "",
         "number": "SAFT0001034",
         "sys_id": "e9823a342d07576441102452241289c1ed0ce",
         "sys_updated_by": "admin",
         "opened_by": {
           "link": "https://dev****.service-now.com/api/now/table/sys_user/TOP2",
           "value": "TOP2"
         },
         "sys_created_on": "2022-03-06 05:17:59",
         "location": {
           "link": "https://dev9****.service-now.com/api/now/table/cmn_location/2e32343e0bfc8bcbe5df9",
           "value": "2e3c49b234443352fc8bcbe5df9"
         },
         "state": "new",
         "category": "big",
         "sys_created_by": "admin",
         "assigned_to": ""
       }
     }  
*/

// ServiceNow connection details

let username = "*****"

let password = "***************"

let loginData = String(format: "%@:%@", username, password).data(using: String.Encoding.utf8)!

let base64LoginData = loginData.base64EncodedString()


let urlString = "https://dev*****.service-now.com/api/now/table/x_781299_safety_issue"

let url = URL(string: urlString)

var request = URLRequest(url: url!)

request.allHTTPHeaderFields = [
    "Content-Type": "application/json",
    "Accept": "application/json"
]

// Specify the body and encode it

let ServiceNowRequest = servicenowRequest()

let encoder = JSONEncoder()

let ServiceNowRequestEncoded = try encoder.encode(ServiceNowRequest)

let requestBody = String(data: ServiceNowRequestEncoded, encoding: .utf8)!

do

{
    request.httpBody = requestBody.data(using: String.Encoding.utf8);
}

catch

{
    print ("Error creating data object from json")
}

// Specify the request type

request.httpMethod = "POST"

request.setValue("Basic \(base64LoginData)", forHTTPHeaderField: "Authorization")


// Get the URL Session

let session = URLSession.shared

// Create the data task

let dataTask = session.dataTask(with: request) { (data, response, error) in

    if error == nil && data != nil

    {
        do
        {
            let dictionary = try   JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String:Any]        

            // Decode response from ServiceNow

            do

            {
                let response = try JSONDecoder().decode(servicenowResponse.self, from: data!)
                print(response)
            }

            catch let jsonErr

            {
                print(jsonErr)
            }
        }

        catch

        {
            print ("Error parsing response")
        }
    }
}

// Fire off the data task

dataTask.resume()
Accepted Answer

There a few things I don't understand in your code.

What doc you do with this dictionary ?

            let dictionary = try   JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String:Any]        

You have a result keyword in your JSON file, but I do not see it in the servicenowResponse

You should either declare it in servicenowResponse

struct SomeResponse: Codable {
        var short_description: String = ""
// etc …
}

struct ServiceNowResponse: Codable {
        var someResponse : SomeResponse()
}

or isolate what is inside result for decoder.

Note: struct name should start with upperCase and be CamelCase : ServiceNowResponse

Thank you for pointing me in the right direction :)

Decoding JSON
 
 
Q