Joseph Kessler
Joseph Kessler

Reputation: 133

SwiftUI: Receiving an error when decoding JSON

I have some simple JSON data that I'm trying to decode, but it keeps failing. Here is the JSON. It's supposed to be an array, but at the moment it only has 1 thing in it.

[
    {
        "good" : "You're great",
        "terrible" : "You're terrible"
    }
]

Here is the model that I have in Xcode.

struct Affirmation: Identifiable, Codable {

    var id: UUID = UUID()
    var good: String
    var terrible: String

}

Here is how the data is loaded.

class AffirmationData: ObservableObject {
@Published var affirmations = [Affirmation]()

init() {
    //Load data on initialization
    load()
}

func load() {
    
    //Get URL
    guard let url = Bundle.main.url(forResource: "Affirmations", withExtension: "json")
    else {
        print("Affirmations file not found")
        return
    }
    
    //Get data
    let data = try? Data(contentsOf: url)
    
    do {
        
        //Try to decode
        let affirmations = try JSONDecoder().decode([Affirmation].self, from: data!)
        
        //Set affirmations
        self.affirmations = affirmations
        
    } catch {
        
        //Display error if there is one
        print("Affirmations could not be decoded. Error below.")
        print (error)
        
    }
    
    /*//Decode data
    guard let affirmations = try? JSONDecoder().decode([Affirmation].self, from: data!)
    else {
        print("Affirmations could not be decoded")
        return
    }*/
}
}

Finally, here is the error I'm getting

Affirmations could not be decoded. Error below.
dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around line 1, column 0." UserInfo={NSDebugDescription=Invalid value around line 1, column 0., NSJSONSerializationErrorIndex=0})))

What can I do to resolve this? Also, is it related to how the ID is not in the JSON itself? I was thinking it was that, but I much prefer the ID to be set this way instead if possible. Thanks!

EDIT: I changed it so the ID is in the JSON data as you can see below. It doesn't seem to make a difference. It's the same error.

[
{
    "id" : 1,
    "good" : "You're great",
    "terrible" : "You're terrible"
}
]

struct Affirmation: Identifiable, Codable {

var id: Int
var good: String
var terrible: String
}

Upvotes: 0

Views: 4056

Answers (1)

vadian
vadian

Reputation: 285039

You are going to decode a key which is not part of the JSON.

There are two options:

  1. Add CodingKeys and omit the key id

    private enum CodingKeys: String, CodingKey { case good, terrible }
    
  2. Declare the member in the struct as constant, in this case the compiler skips all members with a default value

    let id = UUID()
    

    however you get a warning:

    immutable property will not be decoded because it is declared with an initial value which cannot be overwritten


Your last example with id : Int does work.

Basically you should declare all decoded struct members as constants which are immutable.

Upvotes: 1

Related Questions