Standard Library
class JsonValue
A JSON value: null, a boolean, a number, a string, an array or an object.
since 0.1.0-alpha.1linuxwindowswasm
Overview
A JsonValue holds exactly one of those kinds. Build values with the labeled constructors (JsonValue::ofStr("x"), JsonValue::ofArray(items), and so on), or get them from json::parse. Test the kind with isNull, isBool, isNum, isStr, isArray and isObject. Read the contents with the as... methods, which give None when the kind does not match, or navigate with at and atOrNone. render and renderPretty turn a value back into JSON text.
Numbers are always stored as floats, so the JSON number 30 is read back as 30.0 and renders as 30.000000. Use asNum() and convert with toInt() when you need an integer.
Description
JsonValue is a single class that represents every kind of JSON value. The language has no type
aliases, so a recursive union such as "null, bool, number, string, array of this, object of this" cannot
be declared; instead each JsonValue carries an integer kind tag and the matching payload.
kind |
JSON value | test |
|---|---|---|
0 |
null |
isNull() |
1 |
true / false |
isBool() |
2 |
number (an IEEE double) | isNum() |
3 |
string | isStr() |
4 |
array | isArray() |
5 |
object | isObject() |
A tree is produced by json::parse, or built by hand with one of the six labeled constructors
JsonValue::ofNull(), ofBool(bool), ofNum(float), ofStr(string), ofArray(Array<JsonValue>) and
ofObject(Map<string, JsonValue>).
There are two ways to read a tree, and they fail differently:
- Typed accessors
asBool(),asNum(),asStr(),asArray()andasObject()returnNonewhen the value is of a different kind. They never throw. - Navigation with
at(int)andat(string)is loud. It throws aRuntimeExceptionwhen the value is not an array (or object), when the index is out of range, or when the key is missing.atOrNone(key)is the quiet object lookup: it returnsNonefor a missing key and for a value that is not an object.
size() is the element count of an array, the entry count of an object, and 0 for every other kind.
render() writes compact JSON, and renderPretty(indent) writes the same value with a line per
element, indented by indent spaces per level; an empty array or object stays on one line as [] or
{}.
Kinds, accessors and navigation
JsonValue n = JsonValue::ofNum(2.5);
JsonValue s = JsonValue::ofStr("hi");
JsonValue a = JsonValue::ofArray([n, s, JsonValue::ofBool(false), JsonValue::ofNull()]);
Map<string, JsonValue> m = Map();
m["k"] = a;
JsonValue o = JsonValue::ofObject(m);
console.writeln("${n.kind} ${s.kind} ${a.kind} ${o.kind}");
console.writeln("${a.size()} ${o.size()} ${s.size()}");
console.writeln((n.asNum() ?? 0.0).toString());
console.writeln((n.asStr() == None).toString());
console.writeln(o.at("k").at(0).render());
console.writeln((o.atOrNone("zz") == None).toString());
try {
s.at(0);
} catch (RuntimeException e) {
console.writeln(e.message);
}
2 3 4 5
4 1 0
2.500000
true
2.500000
true
JsonValue.at(int): not an array
Rules
at(int)throwsJsonValue.at(int): not an arrayon a value that is not an array, and the ordinary bounds error on an index outside the array.at(string)throwsJsonValue.at(string): not an objecton a value that is not an object, and akey not founderror for a missing key.- Number payloads are
float, so a number renders with six decimals:JsonValue::ofNum(3.0).render()is3.000000. - An object keeps its keys in insertion order, and
render()andrenderPretty()write them in that order. - The
kind,b,num,str,itemsandfieldsmembers are public, but code should prefer the typed accessors, which keep akindmismatch from reading a stale payload.
Examples
Pretty-printing
JsonValue a = JsonValue::ofArray([JsonValue::ofNum(2.5), JsonValue::ofStr("hi"), JsonValue::ofNull()]);
console.writeln(a.renderPretty(4));
console.writeln(JsonValue::ofArray([]).renderPretty(2));
[
2.500000,
"hi",
null
]
[]
Examples
Parsing a document and reading it
string text = "{\"name\":\"Ann\",\"age\":30,\"tags\":[\"a\",\"b\"]}";
JsonValue doc = json::parse(text) ?? JsonValue::ofNull();
console.writeln(doc.at("name").asStr() ?? "?");
console.writeln((doc.at("age").asNum() ?? 0.0).toInt());
console.writeln(doc.at("tags").at(1).asStr() ?? "?");
console.writeln(doc.at("tags").size());
console.writeln(doc.at("name").asNum() == None);
console.writeln(doc.render());
Ann
30
b
2
true
{"name":"Ann","age":30.000000,"tags":["a","b"]}
Constructors
ofArray
Create a JSON array.
Parameters
- v
- The elements, in order.
Examples
Array<JsonValue> items = [JsonValue::ofNum(1.0), JsonValue::ofStr("two"), JsonValue::ofNull()];
JsonValue v = JsonValue::ofArray(items);
console.writeln(v.size());
console.writeln(v.render());
3
[1.000000,"two",null]
ofBool
JsonValue::ofBool(bool v)Create a JSON boolean.
Parameters
- v
- The boolean value.
Examples
JsonValue v = JsonValue::ofBool(true);
console.writeln(v.isBool());
console.writeln(v.render());
true
true
ofNull
JsonValue::ofNull()Create the JSON value null.
Examples
JsonValue v = JsonValue::ofNull();
console.writeln(v.isNull());
console.writeln(v.render());
true
null
ofNum
JsonValue::ofNum(float v)Create a JSON number.
Parameters
- v
- The numeric value.
Examples
JsonValue v = JsonValue::ofNum(1.5);
console.writeln(v.isNum());
console.writeln(v.render());
true
1.500000
ofObject
Create a JSON object.
Parameters
- v
- The members, keyed by name.
Examples
Map<string, JsonValue> members;
members = members.with("ok", JsonValue::ofBool(true));
JsonValue v = JsonValue::ofObject(members);
console.writeln(v.size());
console.writeln(v.render());
1
{"ok":true}
ofStr
JsonValue::ofStr(string v)Create a JSON string.
Parameters
- v
- The text of the string.
Examples
JsonValue v = JsonValue::ofStr("say \"hi\"");
console.writeln(v.isStr());
console.writeln(v.render());
true
"say \"hi\""
Fields
b
bool bThe boolean value, meaningful only when kind is 1.
fields
The members of the object, meaningful only when kind is 5.
items
The elements, meaningful only when kind is 4.
kind
int kindThe kind tag: 0 for null, 1 for a boolean, 2 for a number, 3 for a string, 4 for an array and 5 for an object. The is... methods are the usual way to test it.
num
float numThe numeric value, meaningful only when kind is 2.
str
string strThe string value, meaningful only when kind is 3.
Methods
asArray
Read the value as an array of values.
Returns
The elements, or None when the value is not an array.
Examples
JsonValue v = json::parse("[1, 2, 3]") ?? JsonValue::ofNull();
Array<JsonValue>? items = v.asArray();
console.writeln(items != None ? items.length() : 0);
console.writeln(JsonValue::ofNull().asArray() == None);
3
true
See also: isArray
asBool
asBool() -> bool | NoneRead the value as a boolean.
Returns
The boolean, or None when the value is not a boolean.
Examples
console.writeln(JsonValue::ofBool(true).asBool() ?? false);
console.writeln(JsonValue::ofStr("true").asBool() == None);
true
true
See also: isBool
asNum
asNum() -> float | NoneRead the value as a number.
Returns
The number, or None when the value is not a number.
Examples
console.writeln(JsonValue::ofNum(2.5).asNum() ?? 0.0);
console.writeln(JsonValue::ofStr("2.5").asNum() == None);
2.500000
true
See also: isNum
asObject
Read the value as a map of member names to values.
Returns
The members, or None when the value is not an object.
Examples
JsonValue v = json::parse("{\"a\": 1, \"b\": 2}") ?? JsonValue::ofNull();
Map<string, JsonValue>? members = v.asObject();
console.writeln(members != None ? members.length() : 0);
console.writeln(JsonValue::ofNull().asObject() == None);
2
true
See also: isObject
asStr
asStr() -> string | NoneRead the value as a string.
Returns
The string, or None when the value is not a string.
Examples
console.writeln(JsonValue::ofStr("hi").asStr() ?? "none");
console.writeln(JsonValue::ofNum(1.0).asStr() ?? "none");
hi
none
See also: isStr
at
at(int i) -> JsonValueGet an element of an array by position.
Navigation with at is strict: it throws instead of returning None, so a wrong path fails loudly. Use atOrNone or the is... tests when the shape of the data is not known in advance.
Parameters
- i
- The zero-based index.
Returns
The element at that index.
Throws
RuntimeException- when this value is not an array, or when
iis out of range.
Examples
JsonValue v = json::parse("[10, 20, 30]") ?? JsonValue::ofNull();
console.writeln((v.at(1).asNum() ?? 0.0).toInt());
try {
v.at(5);
} catch (RuntimeException e) {
console.writeln(e.message);
}
try {
JsonValue::ofStr("x").at(0);
} catch (RuntimeException e) {
console.writeln(e.message);
}
20
index 5 out of bounds (length 3)
JsonValue.at(int): not an array
at(string key) -> JsonValueGet an object member by name.
Like at(int), this throws when the navigation does not fit the data. Use atOrNone for a lookup that may miss.
Parameters
- key
- The member name.
Returns
The value stored under key.
Throws
RuntimeException- when this value is not an object, or when the object has no member
key.
See also: atOrNone
atOrNone
atOrNone(string key) -> JsonValue | NoneLook up an object member by name, giving None when it is absent.
Unlike at, this never throws: a missing member, and a value that is not an object at all, both give None.
Parameters
- key
- The member name.
Returns
The member's value, or None when this is not an object or has no such member.
Examples
JsonValue v = json::parse("{\"a\": true}") ?? JsonValue::ofNull();
console.writeln(v.atOrNone("a") != None);
console.writeln(v.atOrNone("b") == None);
console.writeln(JsonValue::ofNull().atOrNone("a") == None);
true
true
true
See also: at
isArray
isArray() -> boolTest whether this value is an array.
Returns
true when the kind is array.
Examples
JsonValue v = json::parse("[1, 2]") ?? JsonValue::ofNull();
console.writeln(v.isArray());
console.writeln(v.isObject());
true
false
See also: asArray
isBool
isBool() -> boolTest whether this value is a boolean.
Returns
true when the kind is boolean.
Examples
console.writeln(JsonValue::ofBool(false).isBool());
console.writeln(JsonValue::ofNum(0.0).isBool());
true
false
See also: asBool
isNull
isNull() -> boolTest whether this value is null.
Returns
true when the kind is null.
Examples
JsonValue v = json::parse("null") ?? JsonValue::ofBool(false);
console.writeln(v.isNull());
console.writeln(JsonValue::ofStr("").isNull());
true
false
See also: isBool
isNum
isNum() -> boolTest whether this value is a number.
Returns
true when the kind is number.
Examples
console.writeln(JsonValue::ofNum(2.5).isNum());
console.writeln(JsonValue::ofStr("2.5").isNum());
true
false
See also: asNum
isObject
isObject() -> boolTest whether this value is an object.
Returns
true when the kind is object.
Examples
JsonValue v = json::parse("{\"a\": 1}") ?? JsonValue::ofNull();
console.writeln(v.isObject());
console.writeln(v.isArray());
true
false
See also: asObject
isStr
isStr() -> boolTest whether this value is a string.
Returns
true when the kind is string.
Examples
console.writeln(JsonValue::ofStr("x").isStr());
console.writeln(JsonValue::ofNull().isStr());
true
false
See also: asStr
render
render() -> stringRender the value as compact JSON text.
There is no whitespace between tokens. Strings are escaped (", \, and control characters; non-ASCII text passes through unchanged). Numbers use the float text form, so 30 renders as 30.000000. Object members appear in the map's iteration order.
Returns
The JSON text.
Examples
JsonValue v = json::parse("[1, \"two\", {\"three\": null}]") ?? JsonValue::ofNull();
console.writeln(v.render());
console.writeln(JsonValue::ofStr("line1\nline2").render());
[1.000000,"two",{"three":null}]
"line1\nline2"
See also: renderPretty, parse
renderPretty
renderPretty(int indent) -> stringRender the value as indented, multi-line JSON text.
Each array element and object member goes on its own line, indented by indent spaces per nesting level. Empty arrays and objects render as [] and {}, and scalar values render as render would.
Parameters
- indent
- The number of spaces per nesting level.
Returns
The JSON text.
Examples
JsonValue v = json::parse("{\"tags\":[\"a\",\"b\"],\"empty\":[]}") ?? JsonValue::ofNull();
console.writeln(v.renderPretty(2));
{
"tags": [
"a",
"b"
],
"empty": []
}
See also: render
size
size() -> intGet the number of elements or members.
Returns
The element count of an array, the member count of an object, and 0 for every other kind (including a string).
Examples
console.writeln((json::parse("[1, 2, 3]") ?? JsonValue::ofNull()).size());
console.writeln((json::parse("{\"a\": 1}") ?? JsonValue::ofNull()).size());
console.writeln(JsonValue::ofStr("hello").size());
3
1
0