The Data Couldn't Be Read Because It Isn't in The Correct Format?

后端 未结 2 1764
一整个雨季
一整个雨季 2021-01-27 13:10

I\'m pretty sure my model is correct based on my data, I cannot figure out why I am getting the format error?

JSON:

{
   "1596193200":{
      &qu         


        
相关标签:
2条回答
  • 2021-01-27 13:34

    I strongly suggest to learn how to debug: it includes where to look, what info to get, where to get them, etc, and at the end, fix it.

    That's a good thing that you print the error, most beginner don't.

    print("Failed to create JSON with error: ", error.localizedDescription)
    

    =>

    print("Failed to create JSON with error: ", error)
    

    You'll get a better idea.

    Second, if it failed, print the data stringified. You're supposed to have JSON, that's right. But how often do I see question about that issue, when it fact, the answer wasn't JSON at all (the API never stated it will return JSON), the author were facing an error (custom 404, etc.) and did get a XML/HTML message error etc.

    So, when the parsing fails, I suggest to do:

    print("Failed with data: \(String(data: data, encoding: .utf8))")
    

    Check that the output is a valid JSON (plenty of online validators or apps that do that).

    Now:

    I'm pretty sure my model is correct based on my data,

    Well, yes and no.

    Little tip with Codable when debuting (and not using nested stuff): Do the reverse.

    Make your struct Codable if it's not the case yet (I used Playgrounds)

    struct Call: Codable {
        let clientref: Int?
        let type: String?
    }
    
    
    do {
        let calls: [Call] = [Call(clientref: 1, type: "breakfast"),
                              Call(clientref: 0, type: "lunch"),
                              Call(clientref: 2, type: "dinner")]
        
        let encoder = JSONEncoder()
        encoder.outputFormatting = [.prettyPrinted]
        let jsonData = try encoder.encode(calls)
        let jsonStringified = String(data: jsonData, encoding: .utf8)
        if let string = jsonStringified {
            print(string)
        }
    } catch {
        print("Got error: \(error)")
    }
    

    Output:

    [
      {
        "clientref" : 1,
        "type" : "breakfast"
      },
      {
        "clientref" : 0,
        "type" : "lunch"
      },
      {
        "clientref" : 2,
        "type" : "dinner"
      }
    ]
    

    It doesn't look like. I could only used an array to put various calls inside a single variable, and that's what you meant for decoding, because you wrote [Call].self, so you were expecting an array of Call. We are missing the "1596218400" parts. Wait, could it be a dictionary at top level? Yes. You can see the {} and the fact it uses "keys", not listing one after the others...

    Wait, but now that we printed the full error, does it make more sense now?

    typeMismatch(Swift.Array<Any>, 
                 Swift.DecodingError.Context(codingPath: [],         
                                             debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", 
                                             underlyingError: nil))
    

    Fix:

    let dictionary = try JSONDecoder().decode([String: Call].self, from: data)
    completion(dictionary.values) //since I guess you only want the Call objects, not the keys with the numbers.
    
    0 讨论(0)
  • 2021-01-27 13:48

    From the code you provided it looks like you are trying to decode an Array<Call>, but in the JSON the data is formatted as a Dictionary<String: Call>.

    You should try:

    let call = try JsonDecoder().decode(Dictionary<String: Call>.self, from: data)
    
    0 讨论(0)
提交回复
热议问题