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 = none
}

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 = none
}

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.raw_decode(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.raw_decode(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 the JSON string representation of the value.
  4. Casting non-numeric values to int/float (int()/i64()/f32()/f64()) will return zero.

Constants #

const default_encoder = Encoder{}
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 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 #

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 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) str #

fn (f []Any) str() string

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

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 - TODO

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 - TODO

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 (map[string]Any) str #

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

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

fn (Parser) decode #

fn (mut p Parser) decode() !Any

decode decodes provided JSON

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 {
	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 wr io.Writer) !

encode_value encodes a value to the specific writer.

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
	kind TokenKind
	line int
	col  int
}

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