Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-8001] Codable does not synthesize init(from:) and encode(to:) for computed properties with getters and setters #50534

Open
swift-ci opened this issue Jun 15, 2018 · 4 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. Codable Area → standard library: `Codable` and co. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-8001
Radar None
Original Reporter chih98 (JIRA User)
Type Bug
Environment

Version 10.0 beta

macOS App

Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug, Codable
Assignee @itaiferber
Priority Medium

md5: e5406aaa16f518906980087557b0b602

Issue Description:

struct City : Codable {    
    private enum CodingKeys: String, CodingKey {        
        case coordinates = "latt_long"
    }


    public var coordinates: String? {
        get {
            return "(lat, long)"
        }

        set {
            if let coordString = newValue {
                let coords = coordString.replacingOccurrences(of: " ", with: "")
                let coordsArray = coords.split(separator: ",")
                self.lat = Float(Int("(String(describing: coordsArray.first))") ?? 0)
                self.long = Float(Int("(String(describing: coordsArray.last))") ?? 0)
            }
        }
    }

    /* Coordinates set these */
    private(set) var lat: Float?
    private(set) var long: Float?
}

**Coding.swift:24:14: CodingKey case 'coordinates' does not match any stored properties
@itaiferber
Copy link
Contributor

@swift-ci

@itaiferber
Copy link
Contributor

Marko filed this on my request — this is one case in which you might expect to encode and decode a computed property: the JSON contains one property ("coordinates"), but your model actually cares to split it up into meaningful properties.

Codable indeed doesn't automatically encode or decode computed properties (and I'm pretty sure we don't want to automatically), but the error message here is surprising. It's not that coordinates doesn't correspond to any property, it's just a computed property. (The error messages here don't distinguish between those cases.)

Likely this should be refined to something like

  • "coordinates is a computed property which is not eligible for automatic encoding or decoding (override init(from🙂 and encode(to🙂 to encode it manually)"

  • For CodingKeys which really don't point to an actual property: "<blah> does not match any named property on this type", or something like that

@belkadan
Copy link
Contributor

It seems reasonable to use CodingKeys for computed properties if the stored properties have initial values, but that's going to be tricky to implement.

@itaiferber
Copy link
Contributor

@belkadan Yeah, I was thinking about this a little bit this morning. In general, I think we'd rather not encode/decode computed properties unless specifically requested—e.g. it probably doesn't make much sense to encode a computed let property unless you request it explicitly by including a CodingKey, and encoding/decoding a computed var is iffy too (which is why the design is how it is today). But even if you do request it explicitly, the difficulty in decoding comes from verifying that decoding to a computed property makes sense. All stored properties must already either be decoded per the CodingKeys or left out of the CodingKeys and have a default value, but we get into a tricky situation if you could request

struct Foo : Codable {
    var x: Int
    var y: Int {
        get { return x }
        set { x = newValue * 2 }
    }

    enum CodingKeys : String, CodingKey { case x, y }
}

Say you're decoding from JSON {"x": 3, "y": 4} — should x get set to 3 or 8? The ordering of decoding the properties makes a difference, and right now the ordering in practice is determined by the ordering in the CodingKeys, IIRC. Allowing either the computed property or the stored property would require us to prove what storage the computed property is pointing to, which isn't necessarily possible.

In any case, I think that computed properties should always be ignored unless you explicitly request them in the CodingKeys, and we can improve the error message around this at the very least.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. Codable Area → standard library: `Codable` and co. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

3 participants