0

Here is my JSON which is the response from web service,

{
"Data": [
    {
        "Id": 181670,
        "PatientId": 10086,
        "Form": "{\"Day\":\"14-11-2019\",\"Hour\":\"08:31\"}",
        "Type": 8,
        "Time": "2019-11-14T08:31:00"
    }
],
"Success": true,
"ErrorMessage": null

}

Here is the structure I want it saved to

struct Response: Decodable{

let ErrorMessage: String?
let Success: Bool
var data: [Data]

enum CodingKeys: String, CodingKey {
    case data = "Data"
    case Success, ErrorMessage
}
init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.data= try container.decode([Datas].self, forKey: .data)
    self.Success = try container.decode(Bool.self, forKey: .Success)
    self.ErrorMessage = try container.decode(String?.self, forKey: .ErrorMessage)
}

struct Data: Decodable{
    let `Type`: Int
    let  Id, PatientId : Int64
    let Form,Time: String
    enum CodingKeys: String, CodingKey {
        case Id, PatientId, Form,`Type`,Time
    }
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.PatientId = try container.decode(Int64.self, forKey: .PatientId)
        self.Id = try container.decode(Int64.self, forKey: .Id)
        self.Form = try container.decode(String.self, forKey: .Form)
        self.Time = try container.decode(String.self, forKey: .Time)
        self.`Type` = try container.decode(Int.self, forKey: .`Type`)
     }
 }

}

Then you can decode JSON with:

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let response = try decoder.decode(Response.self, from: data)
print(response.data)

The output when I use this method is as follows:

[]

I have looked at Apple's Documentation on decoding nested structs, but I still do not understand how to do the different levels of the JSON properly.

---My other method for this problem:

let task = URLSession.shared.dataTask(with: request as URLRequest)
    {(data,response,error) -> Void in
        if error != nil
        {
            print(error?.localizedDescription as Any)
            return
        }
        do
        {
            guard error == nil else {
                return
            }

            guard let data = data else {
                return
            }

            //create json object from data
            if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary {
                    print(json)
                    if let success = json["Success"] as? Bool {
                        self.sucBool = success as! Bool
                        if let array: NSArray = json["Data"]! as? NSArray{
                            for obj in array {
                                if let dict = obj as? NSDictionary {
                                    // Now reference the data you need using:
                                    let form= dict.value(forKey: "Form")
                                }
                            }
                        }
                    }
            }
            completionHandler(self.sucBool,nil)
        }
        catch let error as NSError
        {
            print(error.localizedDescription)
            completionHandler(false,error)
        }
    }
    task.resume()

The output when I use this method is as follows:

{
Data =     (
);
ErrorMessage = "<null>";
Success = 1;

}

I can read web service response correctly but casting is false for Data. I thing there is a problem with this line of code about casting:

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

---Also, both methods do not write an error message.

4
  • Have you tried using JSONlint.com validator to check your JSON? Commented Nov 14, 2019 at 15:20
  • show us the error you are getting and make sure that you are getting response and no connection issues. Commented Nov 14, 2019 at 15:26
  • Catch block is skipped. I'm not getting an error and no connection issues. The response is coming but I can't assign it to any object. So output is [ ] . Commented Nov 15, 2019 at 11:36
  • Can you please check my other method for this problem above Commented Nov 15, 2019 at 11:48

2 Answers 2

1
  1. Check your JSON on JSONlint.com as @Yvonne Aburrow mentioned
  2. Refactor your structs. You can write them a lot easier! Example:
struct SomeRoot: Decodable {
    let data: [Data]
    let success: Bool
    let errorMessage: String?
}

struct Data: Decodable {
    let id: Int
    let patientId: Int
    let form: String
    let type: Int
    let time: String
}
do {
    let myFetchedJSON = try JSONDecoder().decode(SomeRoot.self, from: jsonObject!)
    print(myFetchedJSON.data)
} catch {
    print(error.localizedDescription)
}

...some hints:

  • For decoding json the Decodable protocol is enough. The Codable protocol you used is for encoding & decoding.
  • you need to do/catch the try JSONDecoder().deco[...] block. If you print the error in the catch {} block you'll find out what is going wrong
Sign up to request clarification or add additional context in comments.

4 Comments

Another hint: You are discouraged from naming a custom struct Data. It could interfere with Foundation Data.
I suggest if you really want something to be called data you nest it in the SomeRoot struct. Use a extension SomeRoot and wrap it around the Data struct,
Agree 👍🏼 (However -> overloading should prevent this, but still it's definitely not a good practice)
I tried your solution. 'print(myFetchedJSON.data)' -> Output [ ]. I'm checking web service response from the postman , but it's true. There are items in the data array. But it does not read or ı cant casting correctly.
0

The problem is the JSON data is not valid JSON

lexical error: invalid character inside string.
          -11-2019\",\"Hour\":\"08:31\",         "Type": 8,         "T
                     (right here) ------^

Tried to correct the error with the JSON data below:

{
    "Data": [{
        "Id": 181670,
        "PatientId": 10086,
        "Form": "{\"Day\":\"14-11-2019\",\"Hour\":\"08:31\"}",
        "Type": 8,
        "Time": "2019-11-14T08:31:00"
    }],
    "Success": true,
    "ErrorMessage": null
}

1 Comment

Sorry, I typed the json incorrectly. I changed it. You can see above

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.