Search code examples
jsonswiftmappingpartial

Is there a way to only partially create an object from JSON in Swift?


I'm creating a SwiftUI flashcard app, and I have no problem using Codable and following the technique Apple demonstrated with their landmarks tutorial app for importing JSON data in order to create their array of objects.

However, two of my flashcard objects' properties don't need to be loaded from JSON, and I could minimize the text needed in the JSON file if I could initialize those values separately instead of loading them from JSON. The problem is I cannot get JSON data to load without an error unless it maps exactly to ALL the object's properties, even if the missing properties are hardcoded with values.

Here is my object model:

import SwiftUI

class Flashcard: Codable, Identifiable {
    let id: Int
    var status: Int
    let chapter: Int
    let question: String
    let answer: String
    let reference: String
}

Here is JSON that works:

[
  {
    "id": 1,
    "status": 0,
    "chapter": 1,
    "question": "This is the question",
    "answer": "This is the answer",
    "reference": "This is the reference"
  }
  //other card info repeated after with a comma separating each
]

Instead of having "id" and "status" listed unecessarily in the JSON, I would prefer to change the model to something like this:

import SwiftUI

class Flashcard: Codable, Identifiable {
    let id = UUID()
    var status: Int = 0

    //only load these from JSON:
    let chapter: Int
    let question: String
    let answer: String
    let reference: String
}

...and then I theoretically should be able to eliminate "id" and "status" from the JSON (but I can't). Is there a simple way to do this that prevents the error from JSON not mapping completely to the object?


Solution

  • Yes, you can do this by setting the coding keys on your Codable class. Just leave out the ones that you don't want to update from the json.

    class Flashcard: Codable, Identifiable {
        let id = UUID()
        var status: Int = 0
        let chapter: Int
        let question: String
        let answer: String
        let reference: String
    
        enum CodingKeys: String, CodingKey {
            case chapter, question, answer, reference
        }
    }
    

    There is a great article by HackingWithSwift on Codable here