json keys are required to be strings; if my underlying value is a hash, JSON::Any#each should give keys of type String, not of type JSON::Any. Any is a convenience wrapper, so let's make it more convenient.
You can use JSON::Any#as_hash and Hash#each.
the problem with those is that you're then dealing with values of JSON::Type instead of JSON::Any; i want to stay with Any values and not worry about casting
@aeosynth I introduced JSON::Any#to_h and JSON::Any#to_a, which keeps values as JSON::Any, in #3883 just now. Thought?
i mean, this issue is about wanting to do less casting, so introducing new casts doesn't really help. also i think you implemented #3158.
How do you think this patch?
When apply this patch, you can write such a code:
require "json"
json = JSON.parse %({"hello": ["foo", "bar"], "world": 42})
json.each do |value, key|
p value
p typeof(value) # => JSON::Any
p key
p typeof(key) # => String
end
But I don't think it is good idea.
Note: We cannot use key typed String without changing block arguments order because Crystal's block cannot be overloading.
The comment above is why keys can't just be strings. I'm closing this. @aeosynth Please provide your use case, without a use case we have no reasons to change JSON::Any
ok, thanks for explaining.
@asterite But I think JSON::Any#each definition is not so good because it is incompatible with Hash#each in spite of iterating over a Hash, in other words it is not useful against Hash. I think we should decide remove each method or it is specialized for Array.
I'd actually like to remove JSON::Any (and YAML::Any) from the standard library, I think it was a mistake.
@asterite are the constant issues with it's usage that are making you consider that scenario?
@luislavena Yes
@asterite understood. If that is the case, then the pull parser documentation and examples might need a bit of improvement in order to make it more easy to people use those instead of Any alternative.
Also how to combine the pull parser and the #mapping in order to return structured data from the JSON/YAML being parsed.
@luislavena The idea would be to use casting, since JSON is highly dynamic (if you don't want to do that, use JSON.mapping). For example:
json = JSON.parse(string).as(Array) # expect an array as result
json.each do |value|
value = value.as(Hash) # expect each item to be a Hash
value["id"].as(Int) # expect id to be an int
# and so on...
end
In fact this is what we had before JSON::Any, but I somehow thought it was going to be more intuitive to use...
The main issue is that everyone seems to want to use it like in Ruby, but that's impossible in a statically typed language. So it's probably better to face reality and force programmers to cast to the types they want.
@asterite However for people who do know what the limitations of JSON::Any are, it's a useful tool for getting a quick PoC done before moving to JSON.mapping/JSON::PullParser. I guess the question is should crystal optimise for newcomers even at the (admittedly minor) detriment of productivity for people who know the langauge well? I would say not.
https://github.com/SwiftyJSON/SwiftyJSON
The SwiftyJSON project could be a way of doing JSON manipulations. @RX14
Most helpful comment
@luislavena The idea would be to use casting, since JSON is highly dynamic (if you don't want to do that, use
JSON.mapping). For example:In fact this is what we had before
JSON::Any, but I somehow thought it was going to be more intuitive to use...The main issue is that everyone seems to want to use it like in Ruby, but that's impossible in a statically typed language. So it's probably better to face reality and force programmers to cast to the types they want.