6.80. kink/json/JSON

Converts between JSON strings and JSON values. See kink/json/JSON_VAL module for JSON values.

This module supports JSON specified in [RFC 8259].

[RFC 8259] https://tools.ietf.org/html/rfc8259

6.80.1. JSON.parse(Json ...[$config={}])

`parse` decodes a JSON value from a `str` value `Json`.

Config methods:

• C.allow_unpaired_surrogates

• C.on_success($success): default = VAL$identity

• C.on_error($error): default = a function which raises an exception

If `Json` is a valid JSON string, `parse` tail-calls $success with the decoded JSON value.

If `Json` is not a valid JSON string, `parse` tail-calls $error with (Msg, Pos), where `Msg` is a `str` value of the error message, and `Pos` is the position index in `Json` where the error is detected.

Scale of a number

The scale of a number in the result JSON value is normalized to the minimum non-negative number which can represent the number in the JSON. Example:

:JSON.require_from('kink/json/')

stdout.print_line(JSON.parse('42.000').repr)  # => 42
stdout.print_line(JSON.parse('1.23e+5').repr) # => 12300

Unpaired surrogate code points

By default, `parse` treats an unpaired surrogate code point in object member names and string values as an error. If such a code point is found, `parse` tail-calls $error.

If C.allow_unpaired_surrogates is called, `parse` allows unpaired surrogate code points. The constrcuted JSON value is dependent on the runtime. The code point might be removed, or might remain in the `str` value.

Preconditions

`Json` must be a `str` value.

$success must be a function which takes a JSON value.

$error must be a function which takes (Msg, Pos), where `Msg` is a `str` value, and `Pos` is an integer `num` value.

Example

:JSON.require_from('kink/json/')

stdout.print_line(JSON.parse('{"name": "Hakuho", "birthyear": 1985}').repr)
# => (flat_map "birthyear"=>1985 "name"=>"Hakuho")

:analyze_json <- {(:Json)
  JSON.parse(Json){(:P)
    P.on_success{(:Val)
      'parsed as {}'.format(Val.repr)
    }
    P.on_error{(:Msg :Pos)
      'error: {} at {}'.format(Msg Pos)
    }
  }
}

stdout.print_line(analyze_json('42'))
# => parsed as 42

stdout.print_line(analyze_json('broken!'))
# => error: unexpected character at 0

6.80.2. JSON.stringify(Json_val ...[$config={}])

`stringify` converts `Json_val` to a `str` value of JSON.

Config methods:

• C.pretty(...[Indent = two white spaces]): turns on pretty-print mode.

• C.after_colon(After_colon): default = a whitespace in pretry-print mode, an empty `str` otherwise.

• C.after_comma(After_comma): default = an empty `str`.

Format

If pretty-print mode is not turned on, the result JSON is formatted in a single line.

If pretty-print mode is turned on, a line feed is inserted for each entry of objects or arrays. Entries are indented by `Indent` for each nest.

After the colon `:` of each entry of objects, `After_colon` is inserted.

If not in pretty-print mode, after the comma `,` of each entry of objects or arrays, `After_comma` is inserted.

Preconditions

`Json_val` must be a JSON value.

`Indent` must be a `str` value which contains only white spaces and tabs.

`After_colon` must be a `str` value which contains only white spaces and tabs.

`After_comma` must be a `str` value which contains only white spaces and tabs.

Example

:JSON.require_from('kink/json/')
:FLAT_MAP.require_from('kink/container/')

:Json_val <- FLAT_MAP.of('nums' [1 2 3])

stdout.print_line(JSON.stringify(Json_val))
# Output:
#   {"nums":[1,2,3]}

stdout.print_line(
  JSON.stringify(Json_val){(:C)
    C.pretty
  }
)
# Output:
#   {
#     "nums": [
#       1,
#       2,
#       3
#     ]
#   }