module JSON
Overview
The JSON module allows parsing and generating JSON documents.
Parsing and generating with JSON#mapping
Use JSON#mapping
to define how an object is mapped to JSON, making it
the recommended easy, type-safe and efficient option for parsing and generating
JSON. Refer to that module's documentation to learn about it.
Parsing with JSON#parse
JSON#parse
will return an Any
, which is a convenient wrapper around all possible JSON types,
making it easy to traverse a complex JSON structure but requires some casts from time to time,
mostly via some method invocations.
require "json"
value = JSON.parse("[1, 2, 3]") # : JSON::Any
value[0] # => 1
typeof(value[0]) # => JSON::Any
value[0].as_i # => 1
typeof(value[0].as_i) # => Int32
value[0] + 1 # Error, because value[0] is JSON::Any
value[0].as_i + 10 # => 11
The above is useful for dealing with a dynamic JSON structure but is slower than using JSON#mapping
.
Generating with JSON::Builder
Use JSON::Builder
to generate JSON on the fly by directly emitting data
to an IO
.
Generating with to_json
to_json
and to_json(IO)
methods are provided for primitive types, but you
need to define to_json(IO)
for custom objects, either manually or using
JSON#mapping
.
Defined in:
json.crjson/mapping.cr
Class Method Summary
-
.parse(input : String | IO) : Any
Parses a JSON document as a
JSON::Any
. -
.parse_raw(input : String | IO) : Type
Parses a JSON document as a
JSON::Type
.
Macro Summary
-
mapping
This is a convenience method to allow invoking
JSON.mapping
with named arguments instead of with a hash/named-tuple literal. -
mapping(properties, strict = false)
The
JSON.mapping
macro defines how an object is mapped to JSON.
Class Method Detail
Parses a JSON document as a JSON::Type
.
Macro Detail
This is a convenience method to allow invoking JSON.mapping
with named arguments instead of with a hash/named-tuple literal.
The JSON.mapping
macro defines how an object is mapped to JSON.
Example
require "json"
class Location
JSON.mapping(
lat: Float64,
lng: Float64,
)
end
class House
JSON.mapping(
address: String,
location: {type: Location, nilable: true},
)
end
house = House.from_json(%({"address": "Crystal Road 1234", "location": {"lat": 12.3, "lng": 34.5}}))
house.address # => "Crystal Road 1234"
house.location # => #<Location:0x10cd93d80 @lat=12.3, @lng=34.5>
house.to_json # => %({"address":"Crystal Road 1234","location":{"lat":12.3,"lng":34.5}})
Usage
JSON.mapping
must receive a series of named arguments, or a named tuple literal, or a hash literal,
whose keys will define Crystal properties.
The value of each key can be a single type (not a union type). Primitive types (numbers, string, boolean and nil)
are supported, as well as custom objects which use JSON.mapping
or define a new
method
that accepts a JSON::PullParser
and returns an object from it.
The value can also be another hash literal with the following options:
- type: (required) the single type described above (you can use
JSON::Any
too) - key: the property name in the JSON document (as opposed to the property name in the Crystal code)
- nilable: if true, the property can be
Nil
. PassingT | Nil
as a type has the same effect. - default: value to use if the property is missing in the JSON document, or if it's
null
andnilable
was not set totrue
. If the default value creates a new instance of an object (for example[1, 2, 3]
orSomeObject.new
), a different instance will be used each time a JSON document is parsed. - emit_null: if true, emits a
null
value for nilable properties (by default nulls are not emitted) - converter: specify an alternate type for parsing and generation. The converter must define
from_json(JSON::PullParser)
andto_json(value, IO)
as class methods. Examples of converters areTime::Format
andTime::EpochConverter
forTime
. - root: assume the value is inside a JSON object with a given key (see
Object.from_json(string_or_io, root)
)
The mapping also automatically defines Crystal properties (getters and setters) for each of the keys. It doesn't define a constructor accepting those arguments, but you can provide an overload.
The macro basically defines a constructor accepting a JSON::PullParser
that reads from
it and initializes this type's instance variables. It also defines a to_json(IO)
method
by invoking to_json(IO)
on each of the properties (unless a converter is specified, in
which case to_json(value, IO)
is invoked).
This macro also declares instance variables of the types given in the mapping.
If strict
is true, unknown properties in the JSON
document will raise a parse exception. The default is false
, so unknown properties
are silently ignored.