Reputation: 1
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.
Upvotes: 0
Views: 116
Reputation: 4743
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
}
Upvotes: 0
Reputation: 501
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:
Decodable
protocol is enough. The Codable
protocol you used is for encoding & decoding.do/catch
the try JSONDecoder().deco[...]
block. If you print the error in the catch {}
block you'll find out what is going wrongUpvotes: 1