JSON Parser and Formatter
Strictly parse and format
JSON
- Uses a
fast
recursive descent parser written in V. - Shows detailed
error messages
with location context. - Optionally supports
JSONC
- ignores single-line and multi-line JavaScript-style comments treating them as whitespace and also trailing commas in arrays ans objects. - Partially supports
JSON5
- allows single-quoted strings. (JSON5 is work in progress.) - Offers both condensed and prettified
JSON
output. - Works with the
Any
type suitable for safe handling of JSON/ YAMLdata. - Supports statically typed data as well.
Uses
prantlf.jany
Synopsis
import prantlf.json { parse, ParseOpts }
// Prepare a JSON string
json := '{
"answer": 42
}'
// Parse a data from the JSON string
any := parse(json, ParseOpts{})
import prantlf.jany { Any, any_int }
import prantlf.json { stringify, StringifyOpts }
// Create a JSON data
any := Any({
'answer': any_int(42)
})
// Format the data to a JSON string
str := stringify(any, StringifyOpts{})
import prantlf.json { unmarshal, UnmarshalOpts }
// Prepare a JSON string
json := '{
"answer": 42
}'
// Declare a target object
struct Config {
answer int
}
// Parse an object from the JSON string
config := unmarshal[Config](json, UnmarshalOpts{})
import prantlf.json { stringify, MarshalOpts }
// Declare a source object
struct Config {
answer int
}
// Assign a source object
config := Config{
answer: 42
}
// Format the object to a JSON string
str := marshal(config, MarshalOpts{})
Installation
You can install this package either from
VPM
v install prantlf.json
v install --git https://github.com/prantlf/v-json
The package with the type
Any
v install prantlf.jany
v install --git https://github.com/prantlf/v-jany
API
The following functions are exported:
parse(input string, opts &ParseOpts) !Any
Parses an
Any
Any
ParseOpts
Name | Type | Default | Description |
---|---|---|---|
ignore_comments |
bool |
false |
ignores single-line and multi-line JavaScript-style comments treating them as whitespace |
ignore_trailing_commas |
bool |
false |
ignores commas behind the last item in an array or in an object |
allow_single_quotes |
bool |
false |
allows single-quoted strings |
any := parse(input, ParseOpts{})!
stringify(any Any, opts &StringifyOpts) !string
Formats an
Any
Any
StringifyOpts
Name | Type | Default | Description |
---|---|---|---|
pretty |
bool |
false |
enables readable formatting using line breaks, spaces and indentation |
trailing_commas |
bool |
false |
inserts commas behind the last item in an array or in an object |
single_quotes |
bool |
false |
format single-quoted instead of double-quoted strings |
escape_slashes |
bool |
false |
escape slashes by prefixing them with a backslash (reverse solidus) |
escape_unicode |
bool |
false |
escape multibyte Unicode characters with
\u
|
str := stringify(any, StringifyOpts{ pretty: true })!
marshal[T](value T, opts &MarshalOpts) !string
Marshals a value of
T
string
MarshalOpts
Name | Type | Default | Description |
---|---|---|---|
enums_as_names |
bool |
false |
stores
string
int
|
pretty |
bool |
false |
enables readable formatting using line breaks, spaces and indentation |
trailing_commas |
bool |
false |
inserts commas behind the last item in an array or in an object |
single_quotes |
bool |
false |
format single-quoted instead of double-quoted strings |
escape_slashes |
bool |
false |
escape slashes by prefixing them with a backslash (reverse solidus) |
escape_unicode |
bool |
false |
escape multibyte Unicode characters with
\u
|
struct Config {
answer int
}
config := Config{ answer: 42 }
str := marshal(config, MarshalOpts{})!
unmarshal[T](input string, opts &UnmarshalOpts) !T
Unmarshals an
Any
T
UnmarshalOpts
Name | Type | Default | Description |
---|---|---|---|
ignore_comments |
bool |
false |
ignores single-line and multi-line JavaScript-style comments treating them as whitespace |
ignore_trailing_commas |
bool |
false |
ignores commas behind the last item in an array or in an object |
allow_single_quotes |
bool |
false |
allows single-quoted strings |
require_all_fields |
bool |
false |
requires a key in the source object for each field in the target struct |
forbid_extra_keys |
bool |
false |
forbids keys in the source object not mapping to a field in the target struct |
cast_null_to_default |
bool |
false |
allows
null
null
|
ignore_number_overflow |
bool |
false |
allows losing precision when unmarshaling numbers to smaller numeric types |
struct Config {
answer int
}
json := '{
"answer": 42
}'
config := unmarshal[Config](json, UnmarshalOpts{})!
unmarshal_to[T](input string, mut obj T, opts &UnmarshalOpts) !
Unmarshals an
Any
T
UnmarshalOpts
Name | Type | Default | Description |
---|---|---|---|
ignore_comments |
bool |
false |
ignores single-line and multi-line JavaScript-style comments treating them as whitespace |
ignore_trailing_commas |
bool |
false |
ignores commas behind the last item in an array or in an object |
allow_single_quotes |
bool |
false |
allows single-quoted strings |
require_all_fields |
bool |
false |
requires a key in the source object for each field in the target struct |
forbid_extra_keys |
bool |
false |
forbids keys in the source object not mapping to a field in the target struct |
cast_null_to_default |
bool |
false |
allows
null
null
|
ignore_number_overflow |
bool |
false |
allows losing precision when unmarshaling numbers to smaller numeric types |
struct Config {
answer int
}
json := '{
"answer": 42
}'
mut config := Config{}
config := unmarshal_to(json, mut config, UnmarshalOpts{})!
Errors
For example, the following code:
parse('42 // ultimate answer', ParseOpts{})
will fail with the following message:
Unexpected "/" at the end of the parsed content on line 1, column 4:
1 | 42 // ultimate answer
| ^
The message is formatted using the error fields, for example:
JsonError {
reason string = 'Unexpected "/" at the end of the parsed content'
offset int = 3
line int = 1
column int = 3
}
Performance
This module is almost 3.8x faster than
x.json2
❯ ./parse_bench.vsh
SPENT 1082.011 ms in parsing condensed with x.json2
SPENT 283.197 ms in parsing condensed with prantlf.json
SPENT 1047.946 ms in parsing pretty with x.json2
SPENT 284.696 ms in parsing pretty with prantlf.json
and almost 3.5x faster when stringifying:
❯ ./stringify_bench.vsh
SPENT 1271.921 ms in stringifying condensed with x.json2
SPENT 380.261 ms in stringifying condensed with prantlf.json
SPENT 1386.552 ms in stringifying pretty with x.json2
SPENT 398.728 ms in stringifying pretty with prantlf.json
TODO
This is a work in progress.
- Support
replacer
for stringify
and marshal
and reviver
for parse
and unmarshal
. - Finish the
JSON5
support. - Help fixing a bug in V - generics doesn't support nested structs.