std/json
Json, a value with the options of the format, for encoding and decoding any Encode/Decode type, and JsonValue for the rare document whose shape is not known ahead of time.
Diese Seite gibt es noch nicht auf Deutsch, deshalb steht sie hier auf Englisch. Zur englischen Seite
Die generierte Referenz von std/json zeigt jede öffentliche Deklaration mit Signatur, Doc-Kommentar und Beispielen.
std/json is JSON as a format of std/encoding, written in TorbScript: Json reads and writes any
Encode/Decode type, and JsonValue is a library type for the rare document whose shape is not known ahead of time,
because Encoder and Decoder are driven by the type being read or written and cannot express "whatever is there" on
their own. Json is in the prelude.
Import#
use Json, JsonValue, JsonError, JsonPointer, JsonPointerError, JsonPointerProblem from "std/json"type User {
name: String
age: Int
}
const json = Json()
const text = json.encode User(name: "Ada", age: 36)
print text
match json.decode<User>(text) {
Ok(user) => print user.name
Fail(error) => print "Rejected: {error}"
}Declarations#
Json#
type Json {
naming: Naming = Naming.Unchanged
strict: Bool = false
flagsAsNames: Bool = false
fn encode<Value: Encode>(value: Value): String
fn decode<Value: Decode>(text: String): Result<Value, JsonError>
fn parse(text: String): Result<JsonValue, JsonError>
fn value<Value: Encode>(value: Value): JsonValue
}
extend Json with Format<JsonError>A Json is the format with its options: naming spells every field name (Naming.SnakeCase writes logLabel as
log_label, and reads it back), and strict makes a field of the input that no type asked for an error instead of
being ignored. flagsAsNames writes a Flags as the array of its case names (["Read","Write"]) and reads it back
from one, where it is a number (3, its mask) by default. encode renders any Encode value as JSON text; decode<Value> parses text and reads it as Value, and
fails on malformed JSON as well as on JSON that does not fit Value, with the field chain it went wrong in. parse
reads text into a JsonValue without knowing its shape; value is any Encode value as the JsonValue it would be
written as, for example to diff two versions of it structurally.
What a value is written as: a record is an object in declaration order, a record that announces no field is its one
value, a case with fields is {"Case":{...}} and one without is "Case", a sequence is an array, a map is an object
whose keys are texts (a number key is quoted, and read back as a number), None is null, and bytes are an array of
numbers. A number without a fraction or an exponent is read as a whole number, so the whole range of Int64 and of
UInt64 round-trips exactly; infinity and "not a number" have no JSON and are written as null.
extend Json with Format<JsonError> additionally gives Json.items<Item>() and Json.encoded<Item>(), the two
Stages that let a byte stream be decoded one element at a time (see std/stream); a [ at the start of
the stream opens one top-level array, and anything else is read as newline- or concatenation-separated values, which
covers NDJSON without a rule of its own.
JsonValue#
type JsonValue {
case Null
case Bool(value: Bool)
case Number(value: Float64)
case String(value: String)
case Array(items: List<Self>)
case Object(entries: Map<String, Self>)
}
extend JsonValue with Encode
extend JsonValue {
fn get(pointer: JsonPointer): Result<JsonValue, JsonPointerError>
}A JSON document without a fixed shape. JSON does not distinguish an integer from a floating-point number, so every
Number carries a Float64. A JsonValue describes itself to any Encoder, not only Json's own.
JsonError#
type JsonError with Show, Error {
static fn syntax(line: Int, message: String): Self
static fn decodeFailed(cause: DecodeError): Self
static fn invalidText(cause: Utf8Error): Self
fn isSyntaxError(): Bool
fn show(): String
fn cause(): Error?
}
extend JsonError with From<Utf8Error>What went wrong turning text into a value: malformed JSON text (syntax, with the line it was found on), JSON that
parsed fine but did not fit the requested type (decodeFailed), or bytes that were not UTF-8 in the first place
(invalidText, from std/stream's Utf8Error). isSyntaxError() tells the first case from the other two;
cause() is the DecodeError or Utf8Error a rejected document failed on, so a report can unwind the chain down to
the field or the byte.
JsonPointer#
type JsonPointer with Show, Equals, Hash {
static fn root(): Self
static fn parse(text: String): Result<Self, JsonPointerError>
static fn parseFragment(text: String): Result<Self, JsonPointerError>
fn text(): String
fn fragment(): String
fn tokens(): List<String>
fn child(token: String): Self
fn parent(): Self?
fn last(): String?
fn show(): String
}
type JsonPointerProblem with Show, Equals, Hash {
case Syntax
case Fragment
case MissingMember
case IndexOutOfRange
case NotAnIndex
case EndOfArray
case NotAContainer
fn show(): String
}
type JsonPointerError with Show, Equals, Error {
pointer: String
problem: JsonPointerProblem
message: String
fn show(): String
}A JsonPointer is the address of one value inside a JSON document (RFC 6901): a list of reference tokens, each the name
of an object member or the index of an array item. The empty list is the root, the whole document. It has two spellings
that are one pointer: the string form /foo/0, where ~0 stands for a ~ and ~1 for a / inside a token, and the
URI fragment form of section 6, the same text percent-encoded to sit behind a #. parse reads the first and
parseFragment the second, text() and fragment() write them, and tokens() are the unescaped names and indexes.
child, parent and last walk up and down without touching the pointer they are called on.
JsonValue.get follows a pointer through a document. A token on an array is a decimal index without a sign or a leading
zero, and -, the position after the last item, is kept as a token but holds no value, so get refuses it. Every
failure is a JsonPointerError that names the pointer text and says which JsonPointerProblem it is: not a pointer,
not a fragment, a missing member, an index out of range, a token that is no index, -, or a token on a value that is not
an object or array.
use Json, JsonPointer from "std/json"
const text = "\{\"users\": [\{\"name\": \"Ada\"\}, \{\"name\": \"Grace\"\}]\}"
match Json().parse(text) {
Ok(document) => {
match JsonPointer.parse("/users/1/name") {
Ok(pointer) => print document.get(pointer)
Fail(problem) => print "Not a pointer: {problem}"
}
}
Fail(problem) => print "Not JSON: {problem}"
}Related#
- std/encoding -
Encode,Decode,NamingandFormat, whichJsonimplements. - std/stream - the
StagesJson.itemsandJson.encodedanswer. - The standard library - the other packages.