Replace `#as_json` with `#to_h` because of wrong object value parsing
What is the current behavior?
The Deserialization module use as_json to represent input params as JSON. But it change all objects (uploaded files, rails models, etc) to strings. Same as use to_s on them.
Example:
params = { data: { attributes: { file: ::File.new(any_existing_filepath) } } }
params.as_json.deep_stringify_keys.dig('data', 'attributes', 'file').class # => String
params.to_h.deep_stringify_keys.dig('data', 'attributes', 'file').class # => File
What is the new behavior?
File attributes in deserialized data have the correct type
Checklist
Please make sure the following requirements are complete:
- [x] Tests for the changes have been added (for bug fixes / features)
- [x] Docs have been reviewed and added / updated if needed (for bug fixes / features)
- [ ] All automated checks pass (CI/CD)
@relaxcore this looks good, except for the part with with_indifferent_access (I'm trying to stay away from Rails stuff).
I imagine you're using the jsonapi_deserialize as part of a multipart request, please correct me if I'm wrong?!
Thank you!
@stas you're right 😄
Just replaced #with_indifferent_access method with #deep_stringify_keys. Should be okay as well
@relaxcore that's still ActiveSupport :honey_pot:
Let's just leave it without :)
@stas it won't work in this way just after #to_h. As I understood, keys should be a strings, not symbols
{ data: {} }.as_json.keys.first.class # => String
{ data: {} }.to_h.keys.first.class # => Symbol
BTW, #as_json is also ActiveSupport 😸
@relaxcore consider using #transform_keys(&:to_s):
https://devdocs.io/ruby~3/hash#method-i-transform_keys
@stas that's also not a good idea, cause it won't "stringify" nested keys, like attributes, etc. With current #as_json logic all nested keys are strings
@relaxcore sorry for the delay. Before we look into technical solutions here, would you be kind to explain a bit what's the use-case here.
From my side it's hard to understand how you ended up deserializing a JSONAPI request with a file upload, since it usually requires an application/json content-type. Are you sending multipart requests and trying to stick to JSONAPI format?
@stas Everything is pretty simple and as you said. Just have one multipart request and find such behavior
@relaxcore sorry for the delay here.
Please let me know if you're still interested in wrapping this up.
What I'd like to suggest here is to make the support for deep_stringify_keys pluggable, in a similar way it's done here:
https://github.com/stas/jsonapi.rb/blob/master/lib/jsonapi/deserialization.rb#L1-L9
It looks like dry-transformer can be used here
https://github.com/dry-rb/dry-transformer/blob/master/lib/dry/transformer/hash.rb
Please let me know what you think. Thanks again for sending the PR.
Bump. Any updates on this?