Title here
Summary here
Our program will demonstrate JSON encoding and decoding in Crystal, including handling of basic data types and custom structures.
require "json"
# We'll use these two structs to demonstrate encoding and
# decoding of custom types below.
class Response1
include JSON::Serializable
property page : Int32
property fruits : Array(String)
end
# You can use annotations on struct field declarations
# to customize the encoded JSON key names.
class Response2
include JSON::Serializable
@[JSON::Field(key: "page")]
property page : Int32
@[JSON::Field(key: "fruits")]
property fruits : Array(String)
end
# First we'll look at encoding basic data types to
# JSON strings. Here are some examples for atomic values.
puts JSON.parse("true")
puts JSON.parse("1")
puts JSON.parse("2.34")
puts JSON.parse("\"crystal\"")
# And here are some for arrays and hashes, which encode
# to JSON arrays and objects as you'd expect.
slc_d = ["apple", "peach", "pear"]
puts slc_d.to_json
map_d = {"apple" => 5, "lettuce" => 7}
puts map_d.to_json
# The JSON module can automatically encode your
# custom data types. It will include all instance
# variables in the encoded output and will by default
# use those names as the JSON keys.
res1_d = Response1.new
res1_d.page = 1
res1_d.fruits = ["apple", "peach", "pear"]
puts res1_d.to_json
# You can use annotations on struct field declarations
# to customize the encoded JSON key names. Check the
# definition of `Response2` above to see an example
# of such annotations.
res2_d = Response2.new
res2_d.page = 1
res2_d.fruits = ["apple", "peach", "pear"]
puts res2_d.to_json
# Now let's look at decoding JSON data into Crystal
# values. Here's an example for a generic data structure.
byt = %({"num":6.13,"strs":["a","b"]})
# We need to parse the JSON string to get a JSON::Any object.
dat = JSON.parse(byt)
puts dat
# In order to use the values in the parsed JSON,
# we'll need to access them using the appropriate methods.
# For example here we get the value of `num` as a Float64.
num = dat["num"].as_f
puts num
# Accessing nested data requires a series of method calls.
strs = dat["strs"].as_a
str1 = strs[0].as_s
puts str1
# We can also decode JSON into custom data types.
# This has the advantages of adding additional
# type-safety to our programs and eliminating the
# need for type casts when accessing the decoded data.
str = %({"page": 1, "fruits": ["apple", "peach"]})
res = Response2.from_json(str)
puts res
puts res.fruits[0]
# In the examples above we always used strings as
# intermediates between the data and JSON representation.
# We can also stream JSON encodings directly to IO objects
# like STDOUT or even HTTP response bodies.
d = {"apple" => 5, "lettuce" => 7}
d.to_json(STDOUT)
puts
To run the program, save it as json_example.cr
and use the crystal
command:
$ crystal json_example.cr
true
1
2.34
"crystal"
["apple","peach","pear"]
{"apple":5,"lettuce":7}
{"page":1,"fruits":["apple","peach","pear"]}
{"page":1,"fruits":["apple","peach","pear"]}
{"num":6.13,"strs":["a","b"]}
6.13
a
Response2(@fruits=["apple", "peach"], @page=1)
apple
{"apple":5,"lettuce":7}
We’ve covered the basics of JSON in Crystal here, but check out the JSON module documentation for more details.