"The data couldn’t be read because it is missing" error when decoding JSON in Swift

IosJsonSwift

Ios Problem Overview


I am getting the following error :

The data couldn’t be read because it is missing.

When I run the following code:

struct Indicator: Decodable {
    let section: String
    let key: Int
    let indicator: Int
    let threshold: Int
}
    var indicators = [Indicator]()
    
    do {
        if let file = Bundle.main.url(forResource: "indicators", withExtension: "json") {
            indicators = try JSONDecoder().decode([Indicator].self, from: try Data(contentsOf: file))
        }
    } catch {
        print(error.localizedDescription)
    }

These are in a function, but I have removed them for clarity. I have a code block which is very similar in a different file (I copied this code from there and changed the names essentially) so I'm not sure why it's happening. The json file is valid json and has it's target properly set.

Thanks

Ios Solutions


Solution 1 - Ios

Printing error.localizedDescription is misleading because it displays only a quite meaningless generic error message.

So never use localizedDescription in Decodable catch blocks.

In the simple form just

print(error)

It shows the full error including the crucial information debugDescription and context.Decodable errors are very comprehensive.


While developing code you could catch each Decodable error separately for example

} catch let DecodingError.dataCorrupted(context) {
    print(context)
} catch let DecodingError.keyNotFound(key, context) {
    print("Key '\(key)' not found:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch let DecodingError.valueNotFound(value, context) {
    print("Value '\(value)' not found:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch let DecodingError.typeMismatch(type, context)  {
    print("Type '\(type)' mismatch:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch {
    print("error: ", error)
}

It shows only the most significant information.

Solution 2 - Ios

I just solved a similar issue on my end but for the property list decoder.

The error in this case seems to mean that a key wasn't found and not the data as a whole.

Try making the variables in your struct optional and it should return a nil value where the problem lies.

Solution 3 - Ios

Try printing the actual error instead of just the description. It should give you a message like "No value associated with key someKey (\"actual_key_if_you_defined_your_own\").", which is much more useful than the localizedDescription.

Solution 4 - Ios

"The data couldn’t be read because it is missing"

the error coming from this code:

...catch {
    print(error.localizedDescription)
}

Because: seems that a key is missing or mistyped.

You can check which key is missing by coding like this:

...catch {
    debugPrint(error)
}

Note: If struct keys are different from JSON data keys, see below example: the key in struct is 'title' but in data is 'name'.

struct Photo: Codable {
    var title: String
    var size: Size
    
    enum CodingKeys: String, CodingKey
    {
        case title = "name"
        case size
    }
}

If you mistype 'name', the error will pop up.

Also, if you mistype this 'CodingKeys', you will get the error.

enum CodingKeys:...

Solution 5 - Ios

Just had a same error. I had an error in manual code for decoder. In my code property completedOn was optional, but I was using try instead of try? when decoding it. When the value was missing in json, the decoding would fail for that property. See the code bellow to better understand what I mean.

public var uuid: UUID
public var completedOn: Date?

...

required public convenience init(from decoder: Decoder) throws {
    self.init()

    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.uuid = try container.decode(UUID.self, forKey: .uuid)
    self.completedOn = try? container.decode(Date.self, forKey: .completedOn)
}

Solution 6 - Ios

First make the properties optional then

If your case similar to this try this decodeIfPresent

    `public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    firstName = try container.decodeIfPresent(String.self, forKey: .firstName)
    }`

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJalemView Question on Stackoverflow
Solution 1 - IosvadianView Answer on Stackoverflow
Solution 2 - IosTylerView Answer on Stackoverflow
Solution 3 - IosFizkerView Answer on Stackoverflow
Solution 4 - IosAFAView Answer on Stackoverflow
Solution 5 - IosRaimundas SakalauskasView Answer on Stackoverflow
Solution 6 - IosNithaparanView Answer on Stackoverflow