0

I have a JSON array created using this call:

guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [Any] else {
    print("This is not JSON!!!")
    return
}

I am trying to get elements from the JSON objects in the array to display them using the following code:

struct sWidget: Codable{
    var createdBy: String
    var createdDate: Date
    var status: String
    var widgetNumber: String
    var updatedBy: String
    var updatedDate: Date
}


do {
    let decoder = JSONDecoder()
    for (index, value) in json.enumerated() {
        let currentWidget = try decoder.decode(sWidget.self, from: json[index] as! Data)
        let currentNum = currentWidget.widgetNumber
            //print(currentNum)
        widgetNums.append(currentNum)
    }
}
catch {
    print("decoding error")
}

The code compiles but when I run it I get this error in the output:

Could not cast value of type '__NSDictionaryM' (0x1063c34f8) to 'NSData' (0x1063c1090). 2018-08-09 09:41:02.666713-0500 TruckMeterLogScanner[14259:1223764] Could not cast value of type '__NSDictionaryM' (0x1063c34f8) to 'NSData' (0x1063c1090).

I am still investigating but any tips would be helpful.

Mayur Karmur
  • 2,119
  • 14
  • 35
Jacobi
  • 21
  • 1
  • 6
  • That's normal because `json` is already an Array of Dictionary/Array/String/Int, already serialized, so it won't have `Data` object inside it, so `json[index]` is not a `(NS)Data` object, so `json[index] as! Data` will crash. If you are just interetested in getting the numbers, send after `let widgets = jsonDecoder.decode([sWidget].self, data: content)`, do widgetNums.append(contentsOf: widgets.map{$0.widgetNumber}`. – Larme Aug 09 '18 at 15:01

2 Answers2

0

Did you try that fetching objects like above mentioned? Because i see that you are using Codable. Fetching is very simple with that actually.

let yourObjectArray = JSONDecoder().decode([sWidget].self, data: json as! Data)

May be this line can be buggy but you can fetch them with one line.

Cemal BAYRI
  • 401
  • 5
  • 12
  • I tried using this code but I get a warning about cast from [Any] to unrelated type 'Data' always fails – Jacobi Aug 09 '18 at 15:05
  • let yourObjectArray = try JSONDecoder().decode([sTruck].self, from: json as! Data) – Jacobi Aug 09 '18 at 15:06
  • @Jacobi are you using Alamofire for fetching data? This is a sample fetching func with Alamofire. I wish it will help you. https://gist.github.com/Cemoo/3ed4f5a3eff11082b064e745d3ef6b35 – Cemal BAYRI Aug 10 '18 at 07:49
0

Extending @Cemal BAYRI's answer:

JSONDecoder() throws, so make sure to either us try? or try (don't forget do-catch with try)

guard let data = content as? Data else {
   return [sWidget]()
}

let jsonDecoder = JSONDecoder()

1. try?

let yourObjectArray = try? jsonDecoder.decode([sWidget].self, data: data)

2. try

do {
  let yourObjectArray = try jsonDecoder.decode([sWidget].self, data: data)
} catch let error {
}  

Note: You would need to take care of Data and Date formatting. Below is an example for Date:

jsonDecoder.dateDecodingStrategy = .iso8601

You can also check it out here

Nasir
  • 140
  • 1
  • 8
  • let data = json as? Data is not populating data. It is still nil after this line of code is executed – Jacobi Aug 09 '18 at 15:43
  • Here `json` is name of the variable containing data. From your question, it would be `content`. – Nasir Aug 09 '18 at 15:50
  • content is already a Data type. Am I replacing the Serialization call with the Decoding call? – Jacobi Aug 09 '18 at 15:54
  • Yes. The Decoder replaces Serialization plus all the other steps needed to convert json to models – Nasir Aug 09 '18 at 15:58