module NASON

Overview

The NASON module allows parsing and generating NASON documents.

General type-safe interface

The general type-safe interface for parsing NASON is to invoke T.from_nason on a target type T and pass either a String or IO as an argument.

require "nason"

json_text = %([1, 2, 3])
Array(Int32).from_nason(json_text) # => [1, 2, 3]

json_text = %({"x": 1, "y": 2})
Hash(String, Int32).from_nason(json_text) # => {"x" => 1, "y" => 2}

Serializing is achieved by invoking to_nason, which returns a String, or to_nason(io : IO), which will stream the NASON to an IO.

require "nason"

[1, 2, 3].to_nason            # => "[1,2,3]"
{"x" => 1, "y" => 2}.to_nason # => "{\"x\":1,\"y\":2}"

Most types in the standard library implement these methods. For user-defined types you can define a self.new(pull : NASON::PullParser) for parsing and to_nason(builder : NASON::Builder) for serializing. The following sections show convenient ways to do this using NASON::Serializable.

NOTE NASON 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 "nason"

json_text = %({"1": 2, "3": 4})
Hash(Int32, Int32).from_nason(json_text) # => {1 => 2, 3 => 4}

{1.5 => 2}.to_nason # => "{\"1.5\":2}"

Parsing with NASON.parse

NASON.parse will return an Any, which is a convenient wrapper around all possible NASON types, making it easy to traverse a complex NASON structure but requires some casts from time to time, mostly via some method invocations.

require "nason"

value = NASON.parse("[1, 2, 3]") # : NASON::Any

value[0]               # => 1
typeof(value[0])       # => NASON::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 NASON::Any
value[0].as_i + 10 # => 11

NASON.parse can read from an IO directly (such as a file) which saves allocating a string:

require "nason"

json = File.open("path/to/file.json") do |file|
  NASON.parse(file)
end

Parsing with NASON.parse is useful for dealing with a dynamic NASON structure.

Generating with NASON.build

Use NASON.build, which uses NASON::Builder, to generate NASON by emitting scalars, arrays and objects:

require "nason"

string = NASON.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_nason

to_nason, to_nason(IO) and to_nason(NASON::Builder) methods are provided for primitive types, but you need to define to_nason(NASON::Builder) for custom objects, either manually or using NASON::Serializable.

Defined in:

nason.cr
nason/builder.cr
nason/serialization.cr

Constant Summary

VERSION = {{ (`shards version /srv/crystaldoc.info/github-cyangle-nason-v0.3.3/src`).chomp.stringify }}

Class Method Summary

Class Method Detail

def self.build(io : IO, indent = nil, &) : Nil #

Writes NASON into the given IO. A NASON::Builder is yielded to the block.


[View source]
def self.build(indent = nil, &) #

Returns the resulting String of writing NASON to the yielded NASON::Builder.

require "nason"

string = NASON.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]}>

[View source]
def self.parse(input : String | IO) : Any #

Parses a NASON document as a NASON::Any.


[View source]