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

Simpler JSON manipulation if using JSON.parse #1832

Closed
asterite opened this issue Oct 28, 2015 · 7 comments
Closed

Simpler JSON manipulation if using JSON.parse #1832

asterite opened this issue Oct 28, 2015 · 7 comments

Comments

@asterite
Copy link
Member

Right now when you do JSON.parse(...) it returns a union of all possible JSON types. Handling such object is tedious because you have to cast things as you access them.

A maybe nicer alternative is wrapping such value in a struct that provides some basic methods to traverse it. An example can be found here.

You will be able to do things like:

require "json"

json = JSON.parse %<{"key": [1, 2, 3]}>
json["key"][1].to_i #=> 2

instead of:

require "json"

json = JSON.parse %<{"key": [1, 2, 3]}>
(((json as Hash)["key"] as Array)[1] as Int) #=> 2

In both cases, a runtime exception will be raised if the expected JSON doesn't match the structure we are unpacking (#[](String) will raise if the wrapped object is not a Hash, etc.), but the first code is much nicer and is equally safe.

The only gotcha is that when traversing this wrapper, values will be wrappers: if you want to "unpack" the underlying value you'll have to use to_s, to_i, to_f, to_a, to_h, etc. (in the playground code these have different names, but we can use the more conventional names).

We can reuse the current JSON::Any for this, which is now a module but we can make it a struct.

If we accept this, we could also change YAML.parse to return a similar object.

@kostya
Copy link
Contributor

kostya commented Oct 28, 2015

👍

@sdogruyol
Copy link
Member

This is just what i needed for dynamic JSON parsing. 👍

@ysbaddaden
Copy link
Contributor

A wrapper would be very nice for quickly playing with JSON without the hassle of casting types. Yet, having to deal upfront with a big union type quickly forced me to look at mapping and pull parsers, so it wasn't such a bad thing, because they're incredibly more powerful (validates schema, casts and maps values to objects, etc).

BTW: a JSON.schema macro could load a JSON schema and generate pull-parsers at compile time.

@asterite
Copy link
Member Author

@ysbaddaden Yes, I have the same "fear": if it becomes too easy to navigate a JSON that way maybe people won't use JSON.mapping. However I think there are many cases where the JSON schema is not known upfront or maybe you just need some value of a big JSON and you don't want to define a mapping. I always think it's nice to provide a quick but maybe non-too-performant way to do something and then an alternative way that takes some more time to write but is much more efficient: you can start with the first one and then change it to the second one if it becomes a bottleneck (but in many cases extracting a property from a JSON won't be a bottleneck).

@ozra
Copy link
Contributor

ozra commented Oct 29, 2015

This is super! I've been thinking about this very thing. When writing anything that interfaces via JSON, there's a great chance it's network data, and then the performance of extraction will be minuscule in comparison to transfer time.
Also, promotes the "prototyping ease", while still allowing "hardening" when required, my favourite way of life :-)
+1!

@waterlink
Copy link
Contributor

👍 from my side. I agree that it is possible someone will stop using json_mapping. I am not one of them ;)

@ysbaddaden
Copy link
Contributor

👍 for me too. The advantage of easy manipulation trumps anything else. Despite being very nice, pull parsers are heavy artillery when we just need to quickly deal with some basic JSON files.

asterite pushed a commit that referenced this issue Nov 11, 2015
asterite pushed a commit that referenced this issue Nov 12, 2015
Make `JSON.parse` return `JSON::Any`, and make it easy to traverse a dynamic JSON structure. Fixes #1832
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants