-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Fix JSON, YAML use_*_discriminator
for recursive struct types
#13238
Fix JSON, YAML use_*_discriminator
for recursive struct types
#13238
Conversation
use_*_discriminator
for recursive types under struct deserializationuse_*_discriminator
for recursive struct types
FYI, this code no longer compiles on 1.8 due to this change require "json"
struct U
def self.new(pull : JSON::PullParser) : U?
pull.read_raw
true ? nil : U.new
end
def initialize
end
end
struct T
include JSON::Serializable
getter u : U
end
pp(T.from_json(%({"u": null}))) ... and similar code expressed with converters. It was previously a runtime cast error. |
I think the proper action is to raise right away instead of returning Suppose the deserializer could technically type the variable as |
It is arguable whether |
In our code, we had a module TimeConverter
def self.from_json(pull : JSON::PullParser) : Time?
TIME_FORMAT.parse(pull.read_string)
rescue
nil
end
end
struct Foo
@[JSON::Field(converter: TimeConverter)
getter time : Time # NOT nilable
end It is not strictly related to (In this case, it was a mistake that |
It's unfortunate to see this previously working code break. But I think it's for good. It only worked due to a bug in the first place and as far as I can tell was never intended nor documented behaviour. We could re-enable that behaviour by adding in an appropriate cast in the deserialization logic. But I don't like that. It trades away type safety for no real benefit out of itself only to keep existing code that relied on a bug working. I believe it's best to accept the breaking code. The quality of the library will be better that way. And as the last example shows (#13238 (comment)) the breakage even helps to discover type errors. It's easy to fix the affected code by raising directly in the converter. This is also backwards compatible with older Crystal releases. |
Fixes #13214. This makes sure the temporary variables are not nilable for properties that aren't nilable and have no default values, since otherwise it seems the deserialization method recursively calls itself and breaks type inference.
This was discovered for JSON but applies to YAML as well.