Skip to content

json #

Description

The json module provides encoding/decoding of V data structures to/from JSON. For more details, see also the JSON section of the V documentation

Large i64 and u64 values are encoded as exact decimal JSON numbers, and json.decode preserves those integer values when reading decimal integer input.

Struct fields of type time.Time can be decoded from either a JSON number or from a JSON string in ISO 8601, RFC 3339, or Unix-timestamp form.

Examples

Here is an example of encoding and decoding a V struct with several fields. Note that you can specify different names in the json encoding for the fields, and that you can skip fields too, if needed.

import json

enum JobTitle {
    manager
    executive
    worker
}

struct Employee {
mut:
    name   string
    family string @[json: '-'] // this field will be skipped
    age    int
    salary f32
    title  JobTitle @[json: 'ETitle'] // the key for this field will be 'ETitle', not 'title'
    // the JSON property is omitted while the field keeps its zero/default value
    notes string @[omitempty]
}

fn main() {
    x := Employee{'Peter', 'Begins', 28, 95000.5, .worker, ''}
    println(x)
    s := json.encode(x)
    println('JSON encoding of employee x: ${s}')
    assert s == '{"name":"Peter","age":28,"salary":95000.5,"ETitle":"worker"}'
    mut y := json.decode(Employee, s)!
    assert y != x
    assert y.family == ''
    y.family = 'Begins'
    assert y == x
    println(y)
    ss := json.encode(y)
    println('JSON encoding of employee y: ${ss}')
    assert ss == s
}

JSON field attributes

The json module supports a few field attributes for controlling how struct fields map to JSON:

  • @[json: 'name'] uses a different JSON key for the field.
  • @[json: '-'] skips the field.
  • @[omitempty] omits the field while encoding if it still has its zero/default value.
  • @[raw] decodes the field as raw JSON text instead of decoding it into another V value. This is useful when you want to keep a nested JSON fragment in a string or ?string field.
import json

struct Message {
    payload string  @[raw]
    note    ?string @[omitempty]
}

fn main() {
    msg := json.decode(Message, '{"payload":{"kind":"ping"},"note":""}')!
    assert msg.payload == '{"kind":"ping"}'

    out := json.encode(Message{
        payload: '{"kind":"ping"}'
    })
    assert out == '{"payload":"{\\"kind\\":\\"ping\\"}"}'
}

In the example above, payload keeps the original JSON fragment during decoding, while note is omitted during encoding when it is none.

fn decode #

fn decode(typ voidptr, s string) !voidptr

decode tries to decode the provided JSON string, into a V structure. If it can not do that, it returns an error describing the reason for the parsing failure.

fn encode #

fn encode(x voidptr) string

encode serialises the provided V value as a JSON string, optimised for shortness.

fn encode_pretty #

fn encode_pretty(x voidptr) string

encode_pretty serialises the provided V value as a JSON string, in a formatted way, optimised for viewing by humans.

struct C.cJSON #

struct C.cJSON {
	next        &C.cJSON
	prev        &C.cJSON
	child       &C.cJSON
	type        int
	valuestring &char
	valueint    int
	valuedouble f64
}

As cJSON use libm, we need to link it.