Skip to content

x.json2 #

The name json2 was chosen to avoid any unwanted potential conflicts with the > existing codegen tailored for the main json module which is powered by CJSON.

x.json2 is an experimental JSON parser written from scratch on V.

Usage

encode[T]

import x.json2
import time

struct Person {
mut:
    name     string
    age      ?int = 20
    birthday time.Time
    deathday ?time.Time
}

fn main() {
    mut person := Person{
        name:     'Bob'
        birthday: time.now()
    }
    person_json := json2.encode[Person](person)
    // person_json == {"name": "Bob", "age": 20, "birthday": "2022-03-11T13:54:25.000Z"}
}

decode[T]

import x.json2
import time

struct Person {
mut:
    name     string
    age      ?int = 20
    birthday time.Time
    deathday ?time.Time
}

fn main() {
    resp :='{"name": "Bob", "age": 20, "birthday": "${time.now()}"}'
    person := json2.decode[Person](resp)!
    //
    struct Person {
      mut:
          name "Bob"
          age  20
          birthday "2022-03-11 13:54:25"
      }
    
}

decode[T] is smart and can auto-convert the types of struct fields - this means examples below will have the same result

json2.decode[Person]('{"name": "Bob", "age": 20, "birthday": "2022-03-11T13:54:25.000Z"}')!
json2.decode[Person]('{"name": "Bob", "age": 20, "birthday": "2022-03-11 13:54:25.000"}')!
json2.decode[Person]('{"name": "Bob", "age": "20", "birthday": 1647006865}')!
json2.decode[Person]('{"name": "Bob", "age": "20", "birthday": "1647006865"}}')!

raw decode

import x.json2
import net.http

fn main() {
    resp := http.get('https://reqres.in/api/products/1')!

    // This returns an Any type
    raw_product := json2.decode[json2.Any](resp.body)!
}

Casting Any type / Navigating

import x.json2
import net.http

fn main() {
    resp := http.get('https://reqres.in/api/products/1')!

    raw_product := json2.decode[json2.Any](resp.body)!

    product := raw_product.as_map()
    data := product['data'] as map[string]json2.Any

    id := data['id'].int() // 1
    name := data['name'].str() // cerulean
    year := data['year'].int() // 2000
}

Constructing an Any type

import x.json2

fn main() {
    mut me := map[string]json2.Any{}
    me['name'] = 'Bob'
    me['age'] = 18

    mut arr := []json2.Any{}
    arr << 'rock'
    arr << 'papers'
    arr << json2.null
    arr << 12

    me['interests'] = arr

    mut pets := map[string]json2.Any{}
    pets['Sam'] = 'Maltese Shitzu'
    me['pets'] = pets

    // Stringify to JSON
    println(me.str())
    //{
    //   "name":"Bob",
    //   "age":18,
    //   "interests":["rock","papers","scissors",null,12],
    //   "pets":{"Sam":"Maltese"}
    //}
}

Null Values

x.json2 has a separate Null type for differentiating an undefined value and a null value. To verify that the field you're accessing is a Null, use [typ] is json2.Null.

fn (mut p Person) from_json(f json2.Any) {
    obj := f.as_map()
    if obj['age'] is json2.Null {
        // use a default value
        p.age = 10
    }
}

Casting a value to an incompatible type

x.json2 provides methods for turning Any types into usable types. The following list shows the possible outputs when casting a value to an incompatible type.

  1. Casting non-array values as array (arr()) will return an array with the value as the content.
  2. Casting non-map values as map (as_map()) will return a map with the value as the content.
  3. Casting non-string values to string (str()) will return theJSON string representation of the value.4. Casting non-numeric values to int/float (int()/i64()/f32()/f64()) will return zero.

Encoding using string builder instead of []u8

To be more performant, json2, in PR 20052, decided to use buffers directly instead of Writers. If you want to use Writers you can follow the steps below:

mut sb := strings.new_builder(64)
mut buffer := []u8{}

json2.encode_value(<some value to be encoded here>, mut buffer)!

sb.write(buffer)!

unsafe { buffer.free() }

Constants #

const null = Null{}

fn decode #

fn decode[T](src string) !T

decode is a generic function that decodes a JSON string into the target type.

fn decode_array #

deprecated: use `decode` instead
deprecated_after: 2025-03-18
fn decode_array[T](src string) ![]T

decode_array is a generic function that decodes a JSON string into the array target type.

fn encode #

fn encode[T](val T) string

encode is a generic function that encodes a type into a JSON string.

fn encode_pretty #

fn encode_pretty[T](typed_data T) string

encode_pretty ...

fn fast_raw_decode #

deprecated: use `decode[json.Any]` instead
deprecated_after: 2025-03-18
fn fast_raw_decode(src string) !Any

Same with raw_decode, but skips the type conversion for certain types when decoding a certain value.

fn map_from #

fn map_from[T](t T) map[string]Any

map_from convert a struct to map of Any

fn raw_decode #

fn raw_decode(src string) !Any

Decodes a JSON string into an Any type. Returns an option.

interface Decodable #

interface Decodable {
	from_json(f Any)
}

Decodable is an interface, that allows custom implementations for decoding structs from JSON encoded values

interface Encodable #

interface Encodable {
	json_str() string
}

Decodable is an interface, that allows custom implementations for encoding structs to their string based JSON representations

fn (Any) arr #

fn (f Any) arr() []Any

arr uses Any as an array.

fn (Any) as_map #

fn (f Any) as_map() map[string]Any

as_map uses Any as a map.

fn (Any) bool #

fn (f Any) bool() bool

bool uses Any as a bool.

fn (Any) f32 #

fn (f Any) f32() f32

f32 uses Any as a 32-bit float.

fn (Any) f64 #

fn (f Any) f64() f64

f64 uses Any as a 64-bit float.

fn (Any) i16 #

fn (f Any) i16() i16

i16 uses Any as a 16-bit integer.

fn (Any) i32 #

fn (f Any) i32() i32

i32 uses Any as a 32-bit integer.

fn (Any) i64 #

fn (f Any) i64() i64

i64 uses Any as a 64-bit integer.

fn (Any) i8 #

fn (f Any) i8() i8

i8 uses Any as a 16-bit integer.

fn (Any) int #

fn (f Any) int() int

int uses Any as an integer.

fn (Any) json_str #

fn (f Any) json_str() string

json_str returns the JSON string representation of the Any type.

fn (Any) prettify_json_str #

fn (f Any) prettify_json_str() string

prettify_json_str returns the pretty-formatted JSON string representation of the Any type.

fn (Any) str #

fn (f Any) str() string

str returns the string representation of the Any type. Use the json_str method if you want to use the escaped str() version of the Any type.

fn (Any) to_time #

fn (f Any) to_time() !time.Time

to_time uses Any as a time.Time.

fn (Any) u64 #

fn (f Any) u64() u64

u64 uses Any as a 64-bit unsigned integer.

fn (Parser) decode #

fn (mut p Parser) decode() !Any

decode - decodes provided JSON

fn ([]Any) str #

fn (f []Any) str() string

str returns the JSON string representation of the []Any type.

fn (map[string]Any) str #

fn (f map[string]Any) str() string

str returns the JSON string representation of the map[string]Any type.

enum ValueKind #

enum ValueKind {
	unknown
	array
	object
	string_
	number
}

ValueKind enumerates the kinds of possible values of the Any sumtype.

fn (ValueKind) str #

fn (k ValueKind) str() string

str returns the string representation of the specific ValueKind

struct DecodeError #

struct DecodeError {
	line    int
	column  int
	message string
}

fn (DecodeError) code #

fn (err DecodeError) code() int

code returns the error code of DecodeError

fn (DecodeError) msg #

fn (err DecodeError) msg() string

msg returns the message of the DecodeError

struct Encoder #

struct Encoder {
pub:
	newline              u8
	newline_spaces_count int
	escape_unicode       bool = true
}

Encoder encodes the an Any type into JSON representation. It provides parameters in order to change the end result.

fn (Encoder) encode_value #

fn (e &Encoder) encode_value[T](val T, mut buf []u8) !

encode_value encodes a value to the specific buffer.

struct InvalidTokenError #

struct InvalidTokenError {
	DecodeError
	token    Token
	expected TokenKind
}

fn (InvalidTokenError) code #

fn (err InvalidTokenError) code() int

code returns the error code of the InvalidTokenError

fn (InvalidTokenError) msg #

fn (err InvalidTokenError) msg() string

msg returns the message of the InvalidTokenError

struct Null #

struct Null {
	is_null bool = true
}

Null struct is a simple representation of the null value in JSON.

struct Token #

struct Token {
	lit  []u8      // literal representation of the token
	kind TokenKind // the token number/enum; for quick comparisons
	line int       // the line in the source where the token occurred
	col  int       // the column in the source where the token occurred
}

fn (Token) full_col #

fn (t Token) full_col() int

full_col returns the full column information which includes the length

struct UnknownTokenError #

struct UnknownTokenError {
	DecodeError
	token Token
	kind  ValueKind = .unknown
}

fn (UnknownTokenError) code #

fn (err UnknownTokenError) code() int

code returns the error code of the UnknownTokenError

fn (UnknownTokenError) msg #

fn (err UnknownTokenError) msg() string

msg returns the error message of the UnknownTokenError