-
-
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
[WIP] JSON.mapping: add store_other_attributes_in
flag
#2834
Conversation
My biggest concern is that JSON.mapping({
x: Int32, y: Int32,
}, extra_attributes: {key: "extra", type: Hash(String, JSON::Any)})
JSON.mapping({
x: Int32, y: Int32,
}, extra_attributes: {key: "unparsed", type: String::RawConverter})
|
I like that, but since JSON.mapping({
x: Int32, y: Int32,
}, extra_attributes: {key: "extra"}) # same as raw: false
JSON.mapping({
x: Int32, y: Int32,
}, extra_attributes: {key: "extra", raw: true}) Using We could even support just: |
I'm actually not sure it'll stay "just those two" for ever, I can't say for sure that using a user defined "collector" can't make sense there. |
I really like the concept behind this PR. Just thought I'd chime in on the parameter name: What about JSON.mapping({
x: Int32, y: Int32,
}, other: {key: "extra"})
JSON.mapping({
x: Int32, y: Int32,
}, other: {key: "extra", raw: true}) It would be short and (I believe) more readable. |
I see only one use case for this: the JSON object you get has properties you are not interested about and you just want to keep them to forward them when serializing the object back to JSON, or when passing it somewhere else. So, they are opaque. If they weren't opaque you would mention them in the mapping itself. So I can't imagine why you'd like to treat them in a special way other than a hash of opaque data or a hash of opaque string data. We could probably have converters, or have a callback invoked on each unknown key, passing the pull parser, but that's not really the point, and it would complicate the API a lot. In the case of sidekiq these properties are opaque to the class defining the mapping, and they are passed to plugins which know what type to expect there. Other cases will be similar. Also, the name JSON.mapping({
x: Int32, y: Int32,
}, other: extra)
JSON.mapping({
x: Int32, y: Int32,
}, other: {property: extra})
JSON.mapping({
x: Int32, y: Int32,
}, otra: {property: "extra", raw: true}) |
On the other hand, let me take that back. Here's the use case we are trying to solve. A plugin would like to register an extra attribute to be stored in the job, and later get that attribute back. So maybe we do want to have a callback of some sort, maybe specify which methods on the instance gets called, when an unknown attribute is reached, and pass the pull parser from there, so it's as type safe as possible. |
This PR isn't finished but I'd like to start and discuss the design around this.
Check the added specs to see what this is all about. This idea originated here
The things to discuss are:
JSON.mapping
parameterto_s
on each hash value, but that's not memory efficient if we will lazily parse the string. So, an option to invokepull.read_raw
instead of creating a JSON::Any. I can't come up with a good API for this. Maybe a second parameter,store_other_attributes_as_raw_strings: true
?We could then copy this to
YAML.mapping
.