json/blueprint/value
The JSON value model, byte-bounded parsing, its text form and bridges
to gleam/json.
Numbers retain exact mathematical values and repeated object keys reject.
Erlang uses OTP JSON; JavaScript uses JSON.parse with source retention and
strict duplicate/Unicode checks. Parsed member order is target-specific.
Native syntax diagnostics have no portable source location. JavaScript
requires JSON.parse reviver context.source; unsupported runtimes return
UnsupportedRuntime. There is no alternate parser.
Manually constructed Object values retain the supplied member order.
default_limits() admits at most 1 MiB (1,048,576 bytes). Change that bound
with with_max_bytes. There are no document-depth, value-count or global
numeric-token admission limits. The byte bound is not a heap-memory quota.
Numeric native projection and codec constraints still apply independently.
JavaScript recursion remains subject to the host stack capacity; exhaustion
returns RuntimeCapacityExceeded, not a configured document-depth failure.
to_string renders compact JSON. to_json and decoder bridge native
gleam/json values, whose parsing policy differs from this module.
import json/blueprint/value
pub fn example() {
let limits = value.default_limits() |> value.with_max_bytes(64 * 1024)
case value.parse("{\"tags\": [\"a\"]}", limits) {
Ok(value.Object(members)) -> Ok(members)
Ok(_) -> Error("expected an object")
Error(error) -> Error(value.describe_parse_error(error))
}
}
Types
The key that object found twice.
pub type DuplicateKey {
DuplicateKey(key: String)
}
Constructors
-
DuplicateKey(key: String)
Where a parse failed: byte offset from 0, line and column from 1.
Columns count graphemes. A native diagnostic without a portable source
position uses Location(0, 0, 0); it does not identify the first byte.
pub type Location {
Location(byte_offset: Int, line: Int, column: Int)
}
Constructors
-
Location(byte_offset: Int, line: Int, column: Int)
A parse failure. It carries no input text.
pub type ParseError {
ParseError(location: Location, reason: ParseReason)
}
Constructors
-
ParseError(location: Location, reason: ParseReason)
Why parsing failed. ByteLimitExceeded is the input admission failure.
May gain variants in a minor release; match with a _ branch.
pub type ParseReason {
UnexpectedCharacter
NativeSyntax
UnsupportedRuntime
RuntimeCapacityExceeded
UnexpectedEndOfInput
InvalidUtf8
InvalidUnicodeScalar
ByteLimitExceeded(max: Int)
InvalidNumber(number.NumberError)
DuplicateObjectKey
UnterminatedString
InvalidEscape
InvalidUnicodeEscape
TrailingContent
}
Constructors
-
UnexpectedCharacter -
NativeSyntaxThe native parser rejected the document without a portable location.
-
UnsupportedRuntimeJavaScript lacks JSON.parse reviver source text; no fallback is used.
-
RuntimeCapacityExceededThe host runtime could not finish parsing, independently of byte limits.
-
UnexpectedEndOfInput -
InvalidUtf8 -
InvalidUnicodeScalar -
ByteLimitExceeded(max: Int) -
InvalidNumber(number.NumberError) -
DuplicateObjectKey -
UnterminatedString -
InvalidEscape -
InvalidUnicodeEscape -
TrailingContent
A JSON value. Object members keep their order; the Object constructor
accepts any list, and object rejects a repeated key.
pub type Value {
Null
Bool(Bool)
String(String)
Number(number.Number)
Array(List(Value))
Object(List(#(String, Value)))
}
Constructors
-
Null -
Bool(Bool) -
String(String) -
Number(number.Number) -
Array(List(Value)) -
Object(List(#(String, Value)))
Values
pub fn decoder() -> decode.Decoder(Value)
A decoder of the data that gleam/json’s json.parse produces. Use it to
read a Value through another JSON parser, for example
json.parse(text, value.decoder()).
That parser owns duplicate keys, number precision and size limits: it
keeps one of repeated keys, reads numbers as Int or Float, and does not
keep member order. A float becomes the shortest decimal that reads back
as the same float. Use parse for strict, bounded reading.
pub fn default_limits() -> Limits
Admit at most 1 MiB (1,048,576 bytes) of JSON text.
pub fn describe_parse_error(error: ParseError) -> String
Render a parse error as text such as
invalid JSON at line 2, column 7: unexpected character. The text names
the setter for a limit error and contains no input text.
pub fn is_limit_exceeded(error: ParseError) -> Bool
Whether the input exceeded a bound of Limits, as opposed to being
invalid JSON.
pub fn object(
entries: List(#(String, Value)),
) -> Result(Value, DuplicateKey)
Build an object, rejecting a key that appears twice.
pub fn parse(
source: String,
limits: Limits,
) -> Result(Value, ParseError)
Parse JSON with byte admission, duplicate rejection and exact numbers. Both targets use native parsing; object order may differ between targets. No depth, value-count or global numeric cap is applied.
pub fn parse_bits(
bytes: BitArray,
limits: Limits,
) -> Result(Value, ParseError)
Parse UTF-8 bytes. Byte admission precedes UTF-8 validation. Invalid UTF-8 retains the first invalid byte location independently of the JSON backend.
pub fn to_json(value: Value) -> Result(json.Json, number.Number)
Convert to gleam/json, exactly. An integer becomes json.int (on
JavaScript, only a safe integer); another number becomes json.float
when the float’s printed form reads back as the same number, such as
0.1 or 1e20. Fails with the first number that has no exact
gleam/json form, such as 1e400 or 0.1000000000000000001.
pub fn to_string(value: Value) -> String
Render compact JSON text with no whitespace, keeping member order.
Numbers are exact. A number whose decimal exponent is from -7 to 20, and
on Erlang an integer of at most 50 digits, is written in plain decimal,
such as 12.5 or 0.001; other numbers use number.to_string, such as
1e-9.