3

In Crystal language, what is the difference between JSON::Any and JSON::Type? What are the use cases of this types?

vtambourine
  • 2,109
  • 3
  • 18
  • 27

2 Answers2

4

JSON::Any is a struct, which is returned as a result of parsing. It has convenient methods to access underlying data as_s, as_bool, as_f etc. :

obj = JSON.parse %({"access": true})
p obj.class           # => JSON::Any
p obj["access"]       # => true
p obj["access"].class # => JSON::Any

JSON::Type is an union type of all possible json types. It is used internally by JSON::Any struct to represent the data:

p obj.raw             # => {"access" => true}
p obj.raw.class       # => Hash(String, JSON::Type)
Vitalii Elenhaupt
  • 7,146
  • 3
  • 27
  • 43
  • Ok, that's much clearer now. But what I'm still trying to understand, is what the reasoning behind that? Why all `JSON::Type` methods associated with `raw` word? `JSON.parse` returns `JSON::Any`, but `JSON::parse_raw` returns `JSON::Type`. `JSON::Any#raw` returns `JSON::Type` in turn. Maybe it's simple language difficulties, but why Type is Raw? – vtambourine Dec 29 '17 at 09:40
  • 1
    You are probably confused by this name conventions. `raw` is an object of type `JSON::Type`. It can be `Bool`, `Int64`, `Float64`, `String`, `Hash`, `Array`, `Nil` etc. (just like possible available types in the json format). It looks logical to me. `JSON::Any` is just a convenient wrapper. – Vitalii Elenhaupt Dec 29 '17 at 09:51
  • `JSON.parse_raw` is a method that returns `raw` and doesn't create the wrapper for it. It is simply a more performant analog of `JSON.parse#raw` – Vitalii Elenhaupt Dec 29 '17 at 09:54
  • 1
    Thank you for your explanation. Reading through sources made it more clear. `JSON::Any` struct is simply a convenient wrapper for `JSON::Type` data structures. – vtambourine Dec 29 '17 at 10:23
2

JSON::Type is a recursively-defined "alias":

alias Type = Nil | Bool | Int64 | Float64 | String | Array(Type) | Hash(String, Type)

Aliases are part of Crystal's type grammar. For details, see https://crystal-lang.org/docs/syntax_and_semantics/alias.html

JSON::Any is a Struct (Struct < Value < Object); an instance of JSON::Any holds the "raw" value of any JSON type:

cr(0.24.1) > x=JSON::Any.new("hi")
 => "hi"
icr(0.24.1) > x
 => "hi"
icr(0.24.1) > x.raw
 => "hi"
peak
  • 105,803
  • 17
  • 152
  • 177