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{})!
escape(s string) string
Formats a
string
str := escape('...')!
escape_opt(s string, opts &EscapeOpts) string
Formats a
string
EscapeOpts
Name | Type | Default | Description |
---|---|---|---|
single_quotes |
bool |
false |
escape single quotes, keep double quotes unescaped |
escape_slashes |
bool |
false |
escape slashes by prefixing them with a backslash (reverse solidus) |
escape_unicode |
bool |
false |
escape multibyte Unicode characters with
\u
|
By default, double quotes are considered delimiters, which need escaping. This can be changed by setting
single_quotes
true
str := escape_opt('...', EscapeOpts{ escape_unicode: true })!
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 around 4x faster than
x.json2
❯ ./parse_bench.vsh
SPENT 1130.785 ms in parsing condensed with x.json2
SPENT 282.204 ms in parsing condensed with prantlf.json
SPENT 1071.293 ms in parsing pretty with x.json2
SPENT 271.030 ms in parsing pretty with prantlf.json
and almost 3x faster when stringifying:
❯ ./stringify_bench.vsh
SPENT 1201.283 ms in stringifying condensed with x.json2
SPENT 439.548 ms in stringifying condensed with prantlf.json
SPENT 1307.802 ms in stringifying pretty with x.json2
SPENT 445.283 ms in stringifying pretty with prantlf.json
and almost 4x faster when unmarshalling:
❯ ./unmarshal_bench.vsh
SPENT 155.405 ms in unmarshalling condensed with json
SPENT 1184.805 ms in unmarshalling condensed with x.json2
SPENT 330.345 ms in unmarshalling condensed with prantlf.json
SPENT 153.020 ms in unmarshalling pretty with json
SPENT 1172.505 ms in unmarshalling pretty with x.json2
SPENT 304.557 ms in unmarshalling pretty with prantlf.json
and more than 46x and in the pretty mode more than 68x faster when marshalling:
❯ ./marshal_bench.vsh
SPENT 96.876 ms in marshalling condensed with json
SPENT 516.113 ms in marshalling condensed with x.json2
SPENT 11.678 ms in marshalling condensed with prantlf.json
SPENT 87.807 ms in marshalling pretty with json
SPENT 1027.831 ms in marshalling pretty with x.json2
SPENT 15.724 ms in marshalling pretty with prantlf.json
Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Lint and test your code.
License
Copyright (c) 2023-2024 Ferdinand Prantl
Licensed under the MIT license.