Documentation
¶
Overview ¶
Package astjson provides fast JSON parsing.
Arbitrary JSON may be parsed by fastjson without the need for creating structs or for generating go code. Just parse JSON and get the required fields with Get* functions.
Index ¶
- Constants
- Variables
- func AppendToArray(array, value *Value)
- func DeduplicateObjectKeysRecursively(v *Value)
- func Exists(data []byte, keys ...string) bool
- func GetBool(data []byte, keys ...string) bool
- func GetBytes(data []byte, keys ...string) []byte
- func GetFloat64(data []byte, keys ...string) float64
- func GetInt(data []byte, keys ...string) int
- func GetString(data []byte, keys ...string) string
- func SetNull(v *Value, path ...string)
- func SetValue(v *Value, value *Value, path ...string)
- func Validate(s string) error
- func ValidateBytes(b []byte) error
- func ValueIsNonNull(v *Value) bool
- func ValueIsNull(v *Value) bool
- type Object
- type ParseError
- type Parser
- type Scanner
- type Type
- type Value
- func ArrayValue(a arena.Arena) *Value
- func FalseValue(a arena.Arena) *Value
- func FloatValue(a arena.Arena, f float64) *Value
- func IntValue(a arena.Arena, i int) *Value
- func MergeValues(ar arena.Arena, a, b *Value) (v *Value, changed bool, err error)
- func MergeValuesWithPath(ar arena.Arena, a, b *Value, path ...string) (v *Value, changed bool, err error)
- func MustParse(s string) *Value
- func MustParseBytes(b []byte) *Value
- func NumberValue(a arena.Arena, s string) *Value
- func ObjectValue(a arena.Arena) *Value
- func Parse(s string) (*Value, error)
- func ParseBytes(b []byte) (*Value, error)
- func ParseBytesWithArena(a arena.Arena, b []byte) (*Value, error)
- func ParseWithArena(a arena.Arena, s string) (*Value, error)
- func StringValue(a arena.Arena, s string) *Value
- func StringValueBytes(a arena.Arena, b []byte) *Value
- func TrueValue(a arena.Arena) *Value
- func (v *Value) AppendArrayItems(right *Value)
- func (v *Value) Array() ([]*Value, error)
- func (v *Value) Bool() (bool, error)
- func (v *Value) Del(key string)
- func (v *Value) Exists(keys ...string) bool
- func (v *Value) Float64() (float64, error)
- func (v *Value) Get(keys ...string) *Value
- func (v *Value) GetArray(keys ...string) []*Value
- func (v *Value) GetBool(keys ...string) bool
- func (v *Value) GetFloat64(keys ...string) float64
- func (v *Value) GetInt(keys ...string) int
- func (v *Value) GetInt64(keys ...string) int64
- func (v *Value) GetObject(keys ...string) *Object
- func (v *Value) GetStringBytes(keys ...string) []byte
- func (v *Value) GetUint(keys ...string) uint
- func (v *Value) GetUint64(keys ...string) uint64
- func (v *Value) Int() (int, error)
- func (v *Value) Int64() (int64, error)
- func (v *Value) MarshalTo(dst []byte) []byte
- func (v *Value) Object() (*Object, error)
- func (v *Value) Set(a arena.Arena, key string, value *Value)
- func (v *Value) SetArrayItem(a arena.Arena, idx int, value *Value)
- func (v *Value) String() string
- func (v *Value) StringBytes() ([]byte, error)
- func (v *Value) Type() Type
- func (v *Value) Uint() (uint, error)
- func (v *Value) Uint64() (uint64, error)
Examples ¶
Constants ¶
const MaxDepth = 300
MaxDepth is the maximum depth for nested JSON.
Variables ¶
var ( ErrMergeDifferentTypes = errors.New("cannot merge different types") ErrMergeDifferingArrayLengths = errors.New("cannot merge arrays of differing lengths") ErrMergeUnknownType = errors.New("cannot merge unknown type") )
var (
NullValue = MustParse(`null`)
)
Functions ¶
func AppendToArray ¶
func AppendToArray(array, value *Value)
func DeduplicateObjectKeysRecursively ¶
func DeduplicateObjectKeysRecursively(v *Value)
func Exists ¶
Exists returns true if the field identified by keys path exists in JSON data.
Array indexes may be represented as decimal numbers in keys.
False is returned on error. Use Parser for proper error handling.
Parser is faster when multiple fields must be checked in the JSON.
Example ¶
package main
import (
"fmt"
"github.com/wundergraph/astjson"
)
func main() {
data := []byte(`{"foo": [1.23,{"bar":33,"baz":null}]}`)
fmt.Printf("exists(data.foo) = %v\n", astjson.Exists(data, "foo"))
fmt.Printf("exists(data.foo[0]) = %v\n", astjson.Exists(data, "foo", "0"))
fmt.Printf("exists(data.foo[1].baz) = %v\n", astjson.Exists(data, "foo", "1", "baz"))
fmt.Printf("exists(data.foobar) = %v\n", astjson.Exists(data, "foobar"))
fmt.Printf("exists(data.foo.bar) = %v\n", astjson.Exists(data, "foo", "bar"))
}
Output: exists(data.foo) = true exists(data.foo[0]) = true exists(data.foo[1].baz) = true exists(data.foobar) = false exists(data.foo.bar) = false
func GetBool ¶
GetBool returns boolean value for the field identified by keys path in JSON data.
Array indexes may be represented as decimal numbers in keys.
False is returned on error. Use Parser for proper error handling.
Parser is faster for obtaining multiple fields from JSON.
func GetBytes ¶
GetBytes returns string value for the field identified by keys path in JSON data.
Array indexes may be represented as decimal numbers in keys.
nil is returned on error. Use Parser for proper error handling.
Parser is faster for obtaining multiple fields from JSON.
func GetFloat64 ¶
GetFloat64 returns float64 value for the field identified by keys path in JSON data.
Array indexes may be represented as decimal numbers in keys.
0 is returned on error. Use Parser for proper error handling.
Parser is faster for obtaining multiple fields from JSON.
func GetInt ¶
GetInt returns int value for the field identified by keys path in JSON data.
Array indexes may be represented as decimal numbers in keys.
0 is returned on error. Use Parser for proper error handling.
Parser is faster for obtaining multiple fields from JSON.
Example ¶
package main
import (
"fmt"
"github.com/wundergraph/astjson"
)
func main() {
data := []byte(`{"foo": [233,true, {"bar": [2343]} ]}`)
n1 := astjson.GetInt(data, "foo", "0")
fmt.Printf("data.foo[0] = %d\n", n1)
n2 := astjson.GetInt(data, "foo", "2", "bar", "0")
fmt.Printf("data.foo[2].bar[0] = %d\n", n2)
}
Output: data.foo[0] = 233 data.foo[2].bar[0] = 2343
func GetString ¶
GetString returns string value for the field identified by keys path in JSON data.
Array indexes may be represented as decimal numbers in keys.
An empty string is returned on error. Use Parser for proper error handling.
Parser is faster for obtaining multiple fields from JSON.
Example ¶
package main
import (
"fmt"
"github.com/wundergraph/astjson"
)
func main() {
data := []byte(`{"foo":{"bar":[123,"baz"]}}`)
s := astjson.GetString(data, "foo", "bar", "1")
fmt.Printf("data.foo.bar[1] = %s", s)
}
Output: data.foo.bar[1] = baz
func ValueIsNonNull ¶
func ValueIsNull ¶
Types ¶
type Object ¶
type Object struct {
// contains filtered or unexported fields
}
Object represents JSON object.
Object cannot be used from concurrent goroutines. Use per-goroutine parsers or ParserPool instead.
Cache-friendly layout: hot data first
func (*Object) Del ¶
Del deletes the entry with the given key from o.
Example ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
v := astjson.MustParse(`{"foo": 123, "bar": [1,2], "baz": "xyz"}`)
o, err := v.Object()
if err != nil {
log.Fatalf("cannot otain object: %s", err)
}
fmt.Printf("%s\n", o)
o.Del("bar")
fmt.Printf("%s\n", o)
o.Del("foo")
fmt.Printf("%s\n", o)
o.Del("baz")
fmt.Printf("%s\n", o)
}
Output: {"foo":123,"bar":[1,2],"baz":"xyz"} {"foo":123,"baz":"xyz"} {"baz":"xyz"} {}
func (*Object) Get ¶
Get returns the value for the given key in the o.
Returns nil if the value for the given key isn't found.
The returned value is valid until Parse is called on the Parser returned o.
func (*Object) Set ¶
Set sets (key, value) entry in the o.
The value must be unchanged during o lifetime.
func (*Object) String ¶
String returns string representation for the o.
This function is for debugging purposes only. It isn't optimized for speed. See MarshalTo instead.
func (*Object) Visit ¶
Visit calls f for each item in the o in the original order of the parsed JSON.
f cannot hold key and/or v after returning.
Example ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
s := `{
"obj": { "foo": 1234 },
"arr": [ 23,4, "bar" ],
"str": "foobar"
}`
var p astjson.Parser
v, err := p.Parse(s)
if err != nil {
log.Fatalf("cannot parse json: %s", err)
}
o, err := v.Object()
if err != nil {
log.Fatalf("cannot obtain object from json value: %s", err)
}
o.Visit(func(k []byte, v *astjson.Value) {
switch string(k) {
case "obj":
fmt.Printf("object %s\n", v)
case "arr":
fmt.Printf("array %s\n", v)
case "str":
fmt.Printf("string %s\n", v)
}
})
}
Output: object {"foo":1234} array [23,4,"bar"] string "foobar"
type ParseError ¶
type ParseError struct {
Err error
}
func NewParseError ¶
func NewParseError(err error) *ParseError
func (*ParseError) Error ¶
func (p *ParseError) Error() string
type Parser ¶
type Parser struct {
}
Parser parses JSON.
Parser may be re-used for subsequent parsing.
Parser cannot be used from concurrent goroutines. Use per-goroutine parsers or ParserPool instead.
func (*Parser) Parse ¶
Parse parses s containing JSON.
The returned value is valid until the next call to Parse*.
Use Scanner if a stream of JSON values must be parsed.
Example ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
var p astjson.Parser
v, err := p.Parse(`{"foo":"bar", "baz": 123}`)
if err != nil {
log.Fatalf("cannot parse json: %s", err)
}
fmt.Printf("foo=%s, baz=%d", v.GetStringBytes("foo"), v.GetInt("baz"))
}
Output: foo=bar, baz=123
Example (Reuse) ¶
package main
import (
"fmt"
"log"
"strconv"
"github.com/wundergraph/astjson"
)
func main() {
var p astjson.Parser
// p may be re-used for parsing multiple json strings.
// This improves parsing speed by reducing the number
// of memory allocations.
//
// Parse call invalidates all the objects previously obtained from p,
// so don't hold these objects after parsing the next json.
for i := 0; i < 3; i++ {
s := fmt.Sprintf(`["foo_%d","bar_%d","%d"]`, i, i, i)
v, err := p.Parse(s)
if err != nil {
log.Fatalf("cannot parse json: %s", err)
}
key := strconv.Itoa(i)
fmt.Printf("a[%d]=%s\n", i, v.GetStringBytes(key))
}
}
Output: a[0]=foo_0 a[1]=bar_1 a[2]=2
func (*Parser) ParseBytes ¶
ParseBytes parses b containing JSON.
The returned Value is valid until the next call to Parse*.
Use Scanner if a stream of JSON values must be parsed.
func (*Parser) ParseBytesWithArena ¶
type Scanner ¶
type Scanner struct {
// contains filtered or unexported fields
}
Scanner scans a series of JSON values. Values may be delimited by whitespace.
Scanner may parse JSON lines ( http://jsonlines.org/ ).
Scanner may be re-used for subsequent parsing.
Scanner cannot be used from concurrent goroutines.
Use Parser for parsing only a single JSON value.
Example ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
var sc astjson.Scanner
sc.Init(` {"foo": "bar" }[ ]
12345"xyz" true false null `)
for sc.Next() {
fmt.Printf("%s\n", sc.Value())
}
if err := sc.Error(); err != nil {
log.Fatalf("unexpected error: %s", err)
}
}
Output: {"foo":"bar"} [] 12345 "xyz" true false null
Example (Reuse) ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
var sc astjson.Scanner
// The sc may be re-used in order to reduce the number
// of memory allocations.
for i := 0; i < 3; i++ {
s := fmt.Sprintf(`[%d] "%d"`, i, i)
sc.Init(s)
for sc.Next() {
fmt.Printf("%s,", sc.Value())
}
if err := sc.Error(); err != nil {
log.Fatalf("unexpected error: %s", err)
}
fmt.Printf("\n")
}
}
Output: [0],"0", [1],"1", [2],"2",
func (*Scanner) Init ¶
Init initializes sc with the given s.
s may contain multiple JSON values, which may be delimited by whitespace.
func (*Scanner) InitBytes ¶
InitBytes initializes sc with the given b.
b may contain multiple JSON values, which may be delimited by whitespace.
type Type ¶
type Type int
Type represents JSON type.
const ( // TypeNull is JSON null. TypeNull Type = 0 // TypeObject is JSON object type. TypeObject Type = 1 // TypeArray is JSON array type. TypeArray Type = 2 // TypeString is JSON string type. TypeString Type = 3 // TypeNumber is JSON number type. TypeNumber Type = 4 // TypeTrue is JSON true. TypeTrue Type = 5 // TypeFalse is JSON false. TypeFalse Type = 6 )
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value represents any JSON value.
Call Type in order to determine the actual type of the JSON value.
Value cannot be used from concurrent goroutines. Use per-goroutine parsers or ParserPool instead.
Cache-friendly layout: hot data first, compact structure
func ArrayValue ¶
func FalseValue ¶
func MergeValues ¶
func MergeValuesWithPath ¶
func MustParse ¶
MustParse parses json string s.
The function panics if s cannot be parsed. The function is slower than the Parser.Parse for re-used Parser.
func MustParseBytes ¶
MustParseBytes parses b containing json.
The function panics if b cannot be parsed. The function is slower than the Parser.ParseBytes for re-used Parser.
func ObjectValue ¶
func Parse ¶
Parse parses json string s.
The function is slower than the Parser.Parse for re-used Parser.
func ParseBytes ¶
ParseBytes parses b containing json.
The function is slower than the Parser.ParseBytes for re-used Parser.
func (*Value) AppendArrayItems ¶
func (*Value) Array ¶
Array returns the underlying JSON array for the v.
The returned array is valid until Parse is called on the Parser returned v.
Use GetArray if you don't need error handling.
func (*Value) Bool ¶
Bool returns the underlying JSON bool for the v.
Use GetBool if you don't need error handling.
func (*Value) Del ¶
Del deletes the entry with the given key from array or object v.
Example ¶
package main
import (
"fmt"
"github.com/wundergraph/astjson"
)
func main() {
v := astjson.MustParse(`{"foo": 123, "bar": [1,2], "baz": "xyz"}`)
fmt.Printf("%s\n", v)
v.Del("foo")
fmt.Printf("%s\n", v)
v.Get("bar").Del("0")
fmt.Printf("%s\n", v)
}
Output: {"foo":123,"bar":[1,2],"baz":"xyz"} {"bar":[1,2],"baz":"xyz"} {"bar":[2],"baz":"xyz"}
func (*Value) Exists ¶
Exists returns true if the field exists for the given keys path.
Array indexes may be represented as decimal numbers in keys.
func (*Value) Float64 ¶
Float64 returns the underlying JSON number for the v.
Use GetFloat64 if you don't need error handling.
func (*Value) Get ¶
Get returns value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
nil is returned for non-existing keys path.
The returned value is valid until Parse is called on the Parser returned v.
Example ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
s := `{"foo":[{"bar":{"baz":123,"x":"434"},"y":[]},[null, false]],"qwe":true}`
var p astjson.Parser
v, err := p.Parse(s)
if err != nil {
log.Fatalf("cannot parse json: %s", err)
}
vv := v.Get("foo", "0", "bar", "x")
fmt.Printf("foo[0].bar.x=%s\n", vv.GetStringBytes())
vv = v.Get("qwe")
fmt.Printf("qwe=%v\n", vv.GetBool())
vv = v.Get("foo", "1")
fmt.Printf("foo[1]=%s\n", vv)
vv = v.Get("foo").Get("1").Get("1")
fmt.Printf("foo[1][1]=%s\n", vv)
// non-existing key
vv = v.Get("foo").Get("bar").Get("baz", "1234")
fmt.Printf("foo.bar.baz[1234]=%v\n", vv)
}
Output: foo[0].bar.x=434 qwe=true foo[1]=[null,false] foo[1][1]=false foo.bar.baz[1234]=<nil>
func (*Value) GetArray ¶
GetArray returns array value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
nil is returned for non-existing keys path or for invalid value type.
The returned array is valid until Parse is called on the Parser returned v.
func (*Value) GetBool ¶
GetBool returns bool value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
false is returned for non-existing keys path or for invalid value type.
func (*Value) GetFloat64 ¶
GetFloat64 returns float64 value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
0 is returned for non-existing keys path or for invalid value type.
func (*Value) GetInt ¶
GetInt returns int value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
0 is returned for non-existing keys path or for invalid value type.
func (*Value) GetInt64 ¶
GetInt64 returns int64 value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
0 is returned for non-existing keys path or for invalid value type.
func (*Value) GetObject ¶
GetObject returns object value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
nil is returned for non-existing keys path or for invalid value type.
The returned object is valid until Parse is called on the Parser returned v.
func (*Value) GetStringBytes ¶
GetStringBytes returns string value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
nil is returned for non-existing keys path or for invalid value type.
The returned string is valid until Parse is called on the Parser returned v.
Example ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
s := `[
{"foo": "bar"},
[123, "baz"]
]`
var p astjson.Parser
v, err := p.Parse(s)
if err != nil {
log.Fatalf("cannot parse json: %s", err)
}
fmt.Printf("v[0].foo = %q\n", v.GetStringBytes("0", "foo"))
fmt.Printf("v[1][1] = %q\n", v.GetStringBytes("1", "1"))
fmt.Printf("v[1][0] = %q\n", v.GetStringBytes("1", "0"))
fmt.Printf("v.foo.bar.baz = %q\n", v.GetStringBytes("foo", "bar", "baz"))
}
Output: v[0].foo = "bar" v[1][1] = "baz" v[1][0] = "" v.foo.bar.baz = ""
func (*Value) GetUint ¶
GetUint returns uint value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
0 is returned for non-existing keys path or for invalid value type.
func (*Value) GetUint64 ¶
GetUint64 returns uint64 value by the given keys path.
Array indexes may be represented as decimal numbers in keys.
0 is returned for non-existing keys path or for invalid value type.
func (*Value) Int ¶
Int returns the underlying JSON int for the v.
Use GetInt if you don't need error handling.
func (*Value) Int64 ¶
Int64 returns the underlying JSON int64 for the v.
Use GetInt64 if you don't need error handling.
func (*Value) MarshalTo ¶
MarshalTo appends marshaled v to dst and returns the result.
Example ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
s := `{
"name": "John",
"items": [
{
"key": "foo",
"value": 123.456,
"arr": [1, "foo"]
},
{
"key": "bar",
"field": [3, 4, 5]
}
]
}`
var p astjson.Parser
v, err := p.Parse(s)
if err != nil {
log.Fatalf("cannot parse json: %s", err)
}
// Marshal items.0 into newly allocated buffer.
buf := v.Get("items", "0").MarshalTo(nil)
fmt.Printf("items.0 = %s\n", buf)
// Re-use buf for marshaling items.1.
buf = v.Get("items", "1").MarshalTo(buf[:0])
fmt.Printf("items.1 = %s\n", buf)
}
Output: items.0 = {"key":"foo","value":123.456,"arr":[1,"foo"]} items.1 = {"key":"bar","field":[3,4,5]}
func (*Value) Object ¶
Object returns the underlying JSON object for the v.
The returned object is valid until Parse is called on the Parser returned v.
Use GetObject if you don't need error handling.
func (*Value) Set ¶
Set sets (key, value) entry in the array or object v.
The value must be unchanged during v lifetime.
Example ¶
v := astjson.MustParse(`{"foo":1,"bar":[2,3]}`)
a := arena.NewMonotonicArena()
// Replace `foo` value with "xyz"
v.Set(a, "foo", astjson.MustParse(`"xyz"`))
// Add "newv":123
v.Set(a, "newv", astjson.MustParse(`123`))
fmt.Printf("%s\n", v)
// Replace `bar.1` with {"x":"y"}
v.Get("bar").Set(a, "1", astjson.MustParse(`{"x":"y"}`))
// Add `bar.3="qwe"
v.Get("bar").Set(a, "3", astjson.MustParse(`"qwe"`))
fmt.Printf("%s\n", v)
Output: {"foo":"xyz","bar":[2,3],"newv":123} {"foo":"xyz","bar":[2,{"x":"y"},null,"qwe"],"newv":123}
func (*Value) SetArrayItem ¶
SetArrayItem sets the value in the array v at idx position.
The value must be unchanged during v lifetime.
func (*Value) String ¶
String returns string representation of the v.
The function is for debugging purposes only. It isn't optimized for speed. See MarshalTo instead.
Don't confuse this function with StringBytes, which must be called for obtaining the underlying JSON string for the v.
func (*Value) StringBytes ¶
StringBytes returns the underlying JSON string for the v.
The returned string is valid until Parse is called on the Parser returned v.
Use GetStringBytes if you don't need error handling.
func (*Value) Type ¶
Type returns the type of the v.
Example ¶
package main
import (
"fmt"
"log"
"github.com/wundergraph/astjson"
)
func main() {
s := `{
"object": {},
"array": [],
"string": "foobar",
"number": 123.456,
"true": true,
"false": false,
"null": null
}`
var p astjson.Parser
v, err := p.Parse(s)
if err != nil {
log.Fatalf("cannot parse json: %s", err)
}
fmt.Printf("%s\n", v.Get("object").Type())
fmt.Printf("%s\n", v.Get("array").Type())
fmt.Printf("%s\n", v.Get("string").Type())
fmt.Printf("%s\n", v.Get("number").Type())
fmt.Printf("%s\n", v.Get("true").Type())
fmt.Printf("%s\n", v.Get("false").Type())
fmt.Printf("%s\n", v.Get("null").Type())
}
Output: object array string number true false null