skip to Main Content

I did wrote some code to save some struct to disk in JSON format.
However, if I save it in a variable and keep that and use it to decoded it then the UUID’s are different.

import Foundation
import PlaygroundSupport
import Swift

struct Project: Codable, Identifiable, Hashable  {
    let id: UUID = UUID()
    let id2: String = UUID().uuidString 
    let name: String
}

let project = Project(name: "PP50")
let encodedData = try JSONEncoder().encode(project)
let jsonString = String(data: encodedData,
                        encoding: .utf8)

print(project.id)
print(project.id2)
print(project.name)
print(jsonString)
print("===================")

if let dataFromJsonString = jsonString?.data(using: .utf8) {
    let projectFromData = try JSONDecoder().decode(Project.self, from: dataFromJsonString)
    print(projectFromData)
    print(projectFromData.name)
    print(projectFromData.id) // <<< why is the id and id'2 different
    print(projectFromData.id2)
}

The result is:

826FEC8A-7FE0-4E6C-8DC1-A0DFA4FC75BE
2D15A1B8-B936-4829-8DC2-9C44B261712E
PP50
Optional("{"id":"826FEC8A-7FE0-4E6C-8DC1-A0DFA4FC75BE","id2":"2D15A1B8-B936-4829-8DC2-9C44B261712E","name":"PP50"}")
===================
Project(id: E951D459-3C0E-43A3-B9C6-2CCF2EB1AEE3, id2: "3C97B5C3-054D-4372-800D-9210439F48C2", name: "PP50")
PP50
E951D459-3C0E-43A3-B9C6-2CCF2EB1AEE3
3C97B5C3-054D-4372-800D-9210439F48C2

Maybe a simple answer, but I don’t see it yet.
Why is the outcome of the id different then the one created?
How come? How to solve this?

3

Answers


  1. All you need to do is to var declare your id properties and they will be included in the decoding

    var id: UUID = UUID()
    var id2: String = UUID().uuidString
    
    Login or Signup to reply.
  2. When you create an instance of Project, id and id2 are constants that get default values from UUID() – you can’t modify these values when decoding a JSON.

    id and id2 need to be variables (var), not constants (let). By doing this, the values can be modified by the JSON contents.

    Login or Signup to reply.
  3. As others have said in comments and other answers, let properties declared with initial values are not decoded and the default value will be used. In this case, the default is a new UUID.

    Changing the properties to var will include them in decoding, even with the default values. However, since identifiers probably shouldn’t be mutable, an implementation which keeps the properties as let but has the same externally visible API is to use an explicit initialiser to provide the default values:

    struct Project: Codable, Identifiable, Hashable  {
        let id: UUID
        let id2: String
        let name: String
        
        init(name: String, id: UUID = UUID(), id2: UUID = UUID()) {
            self.name = name
            self.id = id
            self.id2 = id2.uuidString
        }
    }
    

    By providing default values in the initialiser, a Project can still be created with just a name. Since the properties themselves do not have an initialiser, they will be decoded.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search