module JSON
Overview
The JSON module allows parsing and generating JSON documents.
NOTE To use JSON or its children, you must explicitly import it with require "json"
General type-safe interface
The general type-safe interface for parsing JSON is to invoke T.from_json on a
target type T and pass either a String or IO as an argument.
require "json"
json_text = %([1, 2, 3])
Array(Int32).from_json(json_text) # => [1, 2, 3]
json_text = %({"x": 1, "y": 2})
Hash(String, Int32).from_json(json_text) # => {"x" => 1, "y" => 2}
Serializing is achieved by invoking to_json, which returns a String, or
to_json(io : IO), which will stream the JSON to an IO.
require "json"
[1, 2, 3].to_json # => "[1,2,3]"
{"x" => 1, "y" => 2}.to_json # => "{\"x\":1,\"y\":2}"
Most types in the standard library implement these methods. For user-defined types
you can define a self.new(pull : JSON::PullParser) for parsing and
to_json(builder : JSON::Builder) for serializing. The following sections
show convenient ways to do this using JSON::Serializable.
NOTE JSON object keys are always strings but they can still be parsed
and deserialized to other types. To deserialize, define a
T.from_json_object_key?(key : String) : T? method, which can return nil
if the string can't be parsed into that type. To serialize, define a
to_json_object_key : String method can be serialized that way.
All integer and float types in the standard library can be deserialized that way.
require "json"
json_text = %({"1": 2, "3": 4})
Hash(Int32, Int32).from_json(json_text) # => {1 => 2, 3 => 4}
{1.5 => 2}.to_json # => "{\"1.5\":2}"
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].as_i? # => 1
typeof(value[0].as_i?) # => Int32 | Nil
value[0].as_s? # => nil
typeof(value[0].as_s?) # => String | Nil
value[0] + 1 # Error, because value[0] is JSON::Any
value[0].as_i + 10 # => 11
JSON.parse can read from an IO directly (such as a file) which saves
allocating a string:
require "json"
json = File.open("path/to/file.json") do |file|
JSON.parse(file)
end
Parsing with JSON.parse is useful for dealing with a dynamic JSON structure.
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::Serializable.
Defined in:
json.crjson/builder.cr
json/serialization.cr
Class Method Summary
-
.build(indent : String | Int | Nil = nil, &)
Returns the resulting
Stringof writing JSON to the yieldedJSON::Builder. -
.build(io : IO, indent : String | Int | Nil = nil, &) : Nil
Writes JSON into the given
IO. -
.parse(input : String | IO) : Any
Parses a JSON document as a
JSON::Any.
Class Method Detail
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]}>
Accepts an indent parameter which can either be an Int (number of spaces to indent)
or a String, which will prefix each level with the string a corresponding amount of times.