Content-type: text/html; charset=UTF-8
Man page of json
json
Section: RubyLane/JSON Package Commands (n)
Updated: 0.11.0
Index
Return to Main Contents
NAME
json - Parse, manipulate and produce JSON documents
SYNOPSIS
package require rl_json ?0.11.0?
json get jsonValue ?key ...?
json extract jsonValue ?key ...?
json exists jsonValue ?key ...?
json set jsonVariableName ?key ...? value
json unset jsonVariableName ?key ...?
json foreach varlist1 jsonValue1 ?varlist2 jsonValue2 ...? script
json lmap varlist1 jsonValue1 ?varlist2 jsonValue2 ...? script
json amap varlist1 jsonValue1 ?varlist2 jsonValue2 ...? script
json omap varlist1 jsonValue1 ?varlist2 jsonValue2 ...? script
json string value
json number value
json boolean value
json object ?key value ?key value ...??
json array elem ...
json bool value
json normalize jsonValue
json pretty jsonValue
json template jsonValue ?dictionary?
json isnull jsonValue ?key ...?
json type jsonValue ?key ...?
json length jsonValue ?key ...?
json keys jsonValue ?key ...?
json decode bytes ?encoding?
json valid ?-extensions extensionlist? ?-details detailsvar? jsonValue
DESCRIPTION
This package adds a command json to the interpreter, and defines a new
Tcl_Obj type to store the parsed JSON document. The json command
directly manipulates values whose string representation is valid JSON, in a
similar way to how the dict command directly manipulates values whose
string representation is a valid dictionary. It is similar to dict in
performance.
- json get jsonValue ?key ...?
-
Extract the value of a portion of the jsonValue, returns the closest
native Tcl type (other than JSON) for the extracted portion. The key ...
arguments are a path, as described in PATHS below.
- json extract jsonValue ?key ...?
-
Extract the value of a portion of the jsonValue, returns the JSON
fragment. The key ... arguments are a path, as described in PATHS
below.
- json exists jsonValue ?key ...?
-
Tests whether the supplied key path (see PATHS below) resolves to
something that exists in jsonValue (i.e., that it can be used with
json get without error) and is not null. Returns false if the value
named by the path key ... is null.
- json set jsonVariableName ?key ...? value
-
Updates the JSON value stored in the variable jsonVariableName,
replacing the value referenced by key ... (a path as described in
PATHS below) with the JSON value value. If value is
a valid JSON as given by the JSON grammar, it is added as that JSON type,
otherwise it is converted to a JSON string. Thus the following are equivalent
(modulo efficiency):
-
json set doc foo [json string baz]
json set doc bar [json number 123]
json set doc baz [json boolean true]
#------------------------------------------
json set doc foo baz
json set doc bar 123
json set doc baz true
Watch out for unintended behaviour if the value might look like a boolean or
number but not meet the JSON grammar for those types, in which case the value
is converted to a JSON string:
-
json set doc foo [json boolean yes]
# Key "foo" contains the JSON boolean value "true"
json set doc foo yes
# Key "foo" contains the JSON string value "yes"
Constructing the values using [json type] forces the conversion to
the specified JSON type, or throws an exception if that can't be done.
Which is more efficent will depend on the situation:
-
set doc {[]}
for {set i 0} {$i < 100} {incr i} {
json set doc end+1 [json boolean true];# 1
json set doc end+1 true;# 2
}
# 2 will be faster since "true" will be stored as a literal, and converted
# to a JSON boolean. Each loop iteration will just append another reference
# to this static value to the array, whereas 1 will call [json boolean] each
# iteration.
set doc {[]}
for {set i 0} {$i < 100} {incr i} {
json set doc end+1 [json string false$i];# 1
json set doc end+1 false$i;# 2
}
# 1 will be faster since [json string] knows what the type is and directly
# creates the new element as that type. 2 Needs to parse the string to
# determine the type.
- json unset jsonVariableName ?key ...?
-
Updates the JSON value stored in the variable jsonVariableName, removing
the value referenced by key ..., a path as described in PATHS
below. If the path names a entry in an object then that key is removed from the
object. If the path names an element in an array, that element is removed
and all later elements are moved up.
- json template jsonValue ?dictionary?
-
Return a JSON value by interpolating the values from dictionary into the
template, or from variables in the current scope if dictionary is not
supplied, in the manner described in the section TEMPLATES.
- json string value
-
Return a JSON string with the value value.
- json number value
-
Return a JSON number with the value value.
- json boolean value
-
Return a JSON boolean with the value value. Any of the forms accepted by
Tcl_GetBooleanFromObj are accepted and normalized.
- json object ?key value ?key value ...?? -or- json object packed_value
-
Return a JSON object with the each of the keys and values given. value is a list
of two elements, the first being the type {string, number, boolean, null, object, array, json},
and the second being the value. The alternate syntax json object packed_value
takes the list of keys and values as a single arg instead of a list of args, but is
otherwise the same.
- json array ?elem ...?
-
Return a JSON array containing each of the elements given. elem is a list
of two elements, the first being the type {string, number, boolean, null, object, array, json},
and the second being the value.
- json foreach varList1 jsonValue1 ?varList2 jsonValue2 ...? script
-
Evaluate script in a loop in a similar way to the foreach command.
In each iteration, the values stored in the iterator variables in each
varList are the JSON fragments from jsonValue. This command
supports iterating over JSON arrays and JSON objects. In the JSON object
case, the corresponding varList must be a two element list, with the
first specifiying the variable to hold the key and the second the value. In
the JSON array case, the rules are the same as the foreach command.
- json lmap varList1 jsonValue1 ?varList2 jsonValue2 ...? script
-
As for json foreach, except that it is collecting; the result from each
evaluation of script is added to a Tcl list and returned as the result
of the json lmap command. If the script results in a TCL_CONTINUE
code (e.g., the script does continue), that iteration is skipped and no
element is added to the result list. If it results in TCL_BREAK (e.g., the
script does break) the iterations are stopped and the results
accumulated so far are returned.
- json amap varList1 jsonValue1 ?varList2 jsonValue2 ...? script
-
As for json lmap, but the result is a JSON array rather than a list. If
the result of each iteration is a JSON value it is added to the array as-is,
otherwise it is converted to a JSON string.
- json omap varList1 jsonValue1 ?varList2 jsonValue2 ...? script
-
As for json lmap, but the result is a JSON object rather than a list.
The result of each iteration must be a dictionary (or a list of 2n elements,
including n = 0). Tcl_ObjType snooping is done to ensure that the iteration
over the result is efficient for both dict and list cases.
Each entry in the dictionary will be added to the result object. If the value
for each key in the iteration result is a JSON value it is added to the array
as-is, otherwise it is converted to a JSON string.
- json isnull jsonVariableName ?key ...?
-
Return a boolean indicating whether the named JSON value is null.
- json type jsonVariableName ?key ...?
-
Return the type of the named JSON value, one of "object", "array", "string",
"number", "boolean" or "null".
- json length jsonVariableName ?key ...?
-
Return the length of the of the named JSON array, number of entries in the
named JSON object, or number of characters in the named JSON string. Other
value types aren't supported.
- json keys jsonVariableName ?key ...?
-
Return the keys in the of the named JSON object, found by following the path of keys.
- json normalize jsonValue
-
Return a
``normalized''
version of the input jsonValue, i.e., with all optional whitespace
trimmed.
- json pretty jsonValue
-
Returns a pretty-printed string representation of jsonValue. Useful for
debugging or inspecting the structure of JSON data.
- json decode bytes ?encoding?
-
Rl_json operates on characters, as returned from Tcl's Tcl_GetStringFromObj,
not raw bytes, so considerations of encoding are strictly outside of its scope
(other than ignoring a byte order mark if the string starts with one). The
JSON RFC lays out some behaviour for conforming implementations regarding
character encoding, and ensuring that an application using rl_json meets that
standard would be up to the application. Some aspects are not straightforward,
so rl_json provides this utility subcommand that takes binary data in bytes
and returns a character string according to the RFC specified behaviour. If
the optional encoding argument is given, that encoding will be used to
interpret bytes. The supported encodings are those specified in the RFC:
utf-8, utf-16le, utf-16be, utf-32le, utf-32be. If the string starts with a BOM
(byte order mark (U+FFFE)), and no encoding is given, it will be determined
from the encoding of the BOM. All the encodings listed are supported, even if
Tcl lacks support for the utf-16 and utf-32 encodings natively. However,
without native support the conversion will be slow.
This might look something like this in an application:
-
proc readjson file {
set h [open $file rb];# Note that the file is opened in binary mode - no encoding
try {
json decode [read $h]
} finally {
close $h
}
}
- json valid ?-extensions extensionlist? ?-details details? jsonValue
-
Validate jsonValue against the JSON grammar, returning true if it
conforms and false otherwise. A list of extensions to accept can be supplied
with -extensions, with only one currently supported extension:
comments, which accepts JSON documents containing // foo and /*
foo */ style comments anywhere whitespace would be valid. To reject
documents containing comments, set extensionlist to {}.
Validation using this subcommand is about 3 times faster than parsing and
catching a parsing exception, and it allows strict validation against the RFC
without comments.
If validation fails and -details detailsvar is supplied, the variable
detailsvar is set to a dictionary containing the keys:
-
- errmsg
-
A reason for the failure.
- doc
-
The document that failed validation
- char_ofs
-
The character offset into doc that caused validation to fail.
PATHS
Several of the commands (e.g., json get, json exists, json
set and json unset) accept a path specification that names some
subset of the supplied jsonValue. The rules are similar to the
equivalent concept in the dict command, except that the paths used by
json allow indexing into JSON arrays by the integer key (or a string
matching the regex
``^end(-[0-9]+)?$'').
TEMPLATES
The command json template generates JSON documents by interpolating
values into a template from a supplied dictionary or variables in the current
call frame, a flexible mechanism for generating complex documents. The
templates are valid JSON documents containing string values which match the
regex
``^~[SNBJTL]:.+$''.
The second
character determines what the resulting type of the substituted value will be:
-
- S
-
A string.
- N
-
A number.
- B
-
A boolean.
- J
-
A JSON fragment.
- T
-
A JSON template (substitutions are performed on the inserted fragment).
- L
-
A literal. The resulting string is simply everything from the fourth character
onwards (this allows literal strings to be included in the template that would
otherwise be interpreted as the substitutions above).
None of the first three characters for a template may be escaped.
The value inserted is determined by the characters following the substitution
type prefix. When interpolating values from a dictionary they name keys in the
dictionary which hold the values to interpolate. When interpolating from
variables in the current scope, they name scalar or array variables which hold
the values to interpolate. In either case if the named key or variable doesn't
exist, a JSON null is interpolated in its place.
EXCEPTIONS
Exceptions are thrown when attempting to parse a string which isn't valid JSON,
or when a named path is invalid or doesn't exist:
- RL JSON PARSE errormessage string charOfs
-
Thrown when trying to parse a string that isn't valid JSON. The string
element contains the string that failed to parse, and the first invalid character
is at offset charOfs within that string, using 0 based offsets.
- RL JSON BAD_PATH path
-
Thrown when indexing into a JSON value and the specified path isn't valid.
path is the left subset of the path up to first element that caused the
failure.
EXAMPLES
Produce a JSON value from a template:
-
json template {
{
"thing1": "~S:val1",
"thing2": ["a", "~N:val2", "~S:val2", "~B:val2",
"~S:val3", "~L:~S:val1"],
"subdoc1": "~J:subdoc",
"subdoc2": "~T:subdoc"
}
} {
val1 hello
val2 1e6
subdoc {
{ "thing3": "~S:val1" }
}
}
The result (with formatting for readability):
-
{
"thing1":"hello",
"thing2":["a",1000000.0,"1e6",true,null,"~S:val1"],
"subdoc1":{"thing3":"~S:val1"},
"subdoc2":{"thing3":"hello"}
}
Incrementally append an element to an array (similar to dict lappend):
-
set doc {{"foo":[]}}
for {set i 0} {$i < 4} {incr i} {
json set doc foo end+1 [json string "elem: $i"]
}
# $doc is {"foo":["elem 0","elem 1","elem 2","elem 3"]}
Similar to the above, but prepend the elements instead:
-
set doc {{"foo":[]}}
for {set i 0} {$i < 4} {incr i} {
json set doc foo -1 [json string "elem: $i"]
}
# $doc is {"foo":["elem 3","elem 2","elem 1","elem 0"]}
Trim an element out of an array:
-
set doc {["a","b","c"]}
json unset doc 1
# $doc is {["a","c"]}
Implicitly create objects when setting a path that doesn't exist:
-
set doc {{"foo":1}}
json set doc bar baz {"hello, new obj"}
# $doc is {"foo":1,"bar":{"baz":"hello, new obj"}}
Index through objects and arrays (the path elements are unambiguous because the
json types they index into are known at resolve time):
-
set doc {{"foo":["a",{"primes":[2,3,5,7,11,13,17,19]},"c"]}}
json get $doc foo 1 primes end-1
# returns 17
Handle a parse error and display a helpful message indicating the character
that caused the failure:
-
try {
json get {
{
"foo": {
"bar": true,
}
}
} foo bar
} trap {RL JSON PARSE} {errmsg options} {
lassign [lrange [dict get $options -errorcode] 4 5] doc char_ofs
puts stderr "$errmsg\n[string range $doc 0 $char_ofs-1](here -->)[string range $doc $char_ofs end]"
}
Produces:
-
Error parsing JSON value: Illegal character at offset 37
{
"foo": {
"bar": true,
(here -->)}
}
KEYWORDS
json, parsing, formatting
Index
- NAME
-
- SYNOPSIS
-
- DESCRIPTION
-
- PATHS
-
- TEMPLATES
-
- EXCEPTIONS
-
- EXAMPLES
-
- KEYWORDS
-
This document was created by
man2html,
using the manual pages.
Time: 17:04:20 GMT, November 09, 2022