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.build
Use JSON.build
, which uses JSON::Builder
, to generate JSON
by emitting scalars, arrays and objects:
require "json"
string = JSON.build do |json|
json.object do
json.field "name", "foo"
json.field "values" do
json.array do
json.number 1
json.number 2
json.number 3
end
end
end
end
string # => %<{"name":"foo","values":[1,2,3]}>
Generating with to_json
to_json
, to_json(IO)
and to_json(JSON::Builder)
methods are provided
for primitive types, but you need to define to_json(JSON::Builder)
for custom objects, either manually or using JSON#mapping
.
Defined in:
json.crjson/builder.cr
json/mapping.cr
Class Method Summary
-
.build(io : IO, indent = nil, &block)
Writes JSON into the given
IO
. -
.build(indent = nil, &block)
Returns the resulting
String
of writing JSON to the yieldedJSON::Builder
. -
.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(properties, strict = false)
The
JSON.mapping
macro defines how an object is mapped to JSON. -
mapping
This is a convenience method to allow invoking
JSON.mapping
with named arguments instead of with a hash/named-tuple literal.
Class Method Detail
Writes JSON into the given IO
. A JSON::Builder
is yielded to the block.
Returns the resulting String
of writing JSON to the yielded JSON::Builder
.
require "json"
string = JSON.build do |json|
json.object do
json.field "name", "foo"
json.field "values" do
json.array do
json.number 1
json.number 2
json.number 3
end
end
end
end
string # => %<{"name":"foo","values":[1,2,3]}>
Parses a JSON document as a JSON::Type
.
Macro Detail
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 beNil
. PassingT?
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 anull
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, JSON::Builder)
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)
) - setter: if
true
, will generate a setter for the variable,true
by default - getter: if
true
, will generate a getter for the variable,true
by default
This macro by default defines getters and setters for each variable (this can be overrided with setter and getter). The mapping doesn't define a constructor accepting these variables as 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(JSON::Builder)
method
by invoking to_json(JSON::Builder)
on each of the properties (unless a converter is specified, in
which case to_json(value, JSON::Builder)
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.
This is a convenience method to allow invoking JSON.mapping
with named arguments instead of with a hash/named-tuple literal.