Documentation ¶
Overview ¶
Package ajson implements decoding of JSON as defined in RFC 7159 without predefined mapping to a struct of golang, with support of JSONPath.
All JSON structs reflects to a custom struct of Node, witch can be presented by it type and value.
Method Unmarshal will scan all the byte slice to create a root node of JSON structure, with all it behaviors.
Each Node has it's own type and calculated value, which will be calculated on demand. Calculated value saves in atomic.Value, so it's thread safe.
Method JSONPath will returns slice of founded elements in current JSON data, by it's JSONPath.
JSONPath selection described at http://goessner.net/articles/JsonPath/
JSONPath expressions always refer to a JSON structure in the same way as XPath expression are used in combination with an XML document. Since a JSON structure is usually anonymous and doesn't necessarily have a "root member object" JSONPath assumes the abstract name $ assigned to the outer level object.
JSONPath expressions can use the dot–notation
$.store.book[0].title
or the bracket–notation
$['store']['book'][0]['title']
for input pathes. Internal or output pathes will always be converted to the more general bracket–notation.
JSONPath allows the wildcard symbol * for member names and array indices. It borrows the descendant operator '..' from E4X and the array slice syntax proposal [start:end:step] from ECMASCRIPT 4.
Expressions of the underlying scripting language (<expr>) can be used as an alternative to explicit names or indices as in
$.store.book[(@.length-1)].title
using the symbol '@' for the current object. Filter expressions are supported via the syntax ?(<boolean expr>) as in
$.store.book[?(@.price < 10)].title
Here is a complete overview and a side by side comparison of the JSONPath syntax elements with its XPath counterparts.
$ the root object/element @ the current object/element . or [] child operator .. recursive descent. JSONPath borrows this syntax from E4X. * wildcard. All objects/elements regardless their names. [] subscript operator. XPath uses it to iterate over element collections and for predicates. In Javascript and JSON it is the native array operator. [,] Union operator in XPath results in a combination of node sets. JSONPath allows alternate names or array indices as a set. [start:end:step] array slice operator borrowed from ES4. ?() applies a filter (script) expression. () script expression, using the underlying script engine.
JSONPath Script engine ¶
Predefined constant ¶
Package has several predefined constants. You are free to add new one with AddConstant
e math.E float64 pi math.Pi float64 phi math.Phi float64 sqrt2 math.Sqrt2 float64 sqrte math.SqrtE float64 sqrtpi math.SqrtPi float64 sqrtphi math.SqrtPhi float64 ln2 math.Ln2 float64 log2e math.Log2E float64 ln10 math.Ln10 float64 log10e math.Log10E float64 true true bool false false bool null nil interface{}
Supported operations ¶
Package has several predefined operators. You are free to add new one with AddOperator
Operator precedence: https://golang.org/ref/spec#Operator_precedence
Precedence Operator 6 ** 5 * / % << >> & &^ 4 + - | ^ 3 == != < <= > >= =~ 2 && 1 ||
Arithmetic operators: https://golang.org/ref/spec#Arithmetic_operators
** power integers, floats + sum integers, floats, strings - difference integers, floats * product integers, floats / quotient integers, floats % remainder integers & bitwise AND integers | bitwise OR integers ^ bitwise XOR integers &^ bit clear (AND NOT) integers << left shift integer << unsigned integer >> right shift integer >> unsigned integer == equals any != not equals any < less any <= less or equals any > larger any >= larger or equals any =~ equals regex string strings
Supported functions ¶
Package has several predefined functions. You are free to add new one with AddFunction
abs math.Abs integers, floats acos math.Acos integers, floats acosh math.Acosh integers, floats asin math.Asin integers, floats asinh math.Asinh integers, floats atan math.Atan integers, floats atanh math.Atanh integers, floats avg Average array of integers or floats b64decode b64 Decoding string b64encode b64 Encoding string b64encoden b64 Encoding (no padding) string cbrt math.Cbrt integers, floats ceil math.Ceil integers, floats cos math.Cos integers, floats cosh math.Cosh integers, floats erf math.Erf integers, floats erfc math.Erfc integers, floats erfcinv math.Erfcinv integers, floats erfinv math.Erfinv integers, floats exp math.Exp integers, floats exp2 math.Exp2 integers, floats expm1 math.Expm1 integers, floats factorial N! unsigned integer floor math.Floor integers, floats gamma math.Gamma integers, floats j0 math.J0 integers, floats j1 math.J1 integers, floats length len array log math.Log integers, floats log10 math.Log10 integers, floats log1p math.Log1p integers, floats log2 math.Log2 integers, floats logb math.Logb integers, floats not not any pow10 math.Pow10 integer round math.Round integers, floats roundtoeven math.RoundToEven integers, floats sin math.Sin integers, floats sinh math.Sinh integers, floats sqrt math.Sqrt integers, floats tan math.Tan integers, floats tanh math.Tanh integers, floats trunc math.Trunc integers, floats y0 math.Y0 integers, floats y1 math.Y1 integers, floats
Index ¶
- func AddConstant(alias string, value *Node)
- func AddFunction(alias string, function Function)
- func AddOperation(alias string, prior uint8, right bool, operation Operation)
- func Marshal(node *Node) (result []byte, err error)
- func ParseJSONPath(path string) (result []string, err error)
- func Paths(array []*Node) []string
- type Error
- type ErrorType
- type Function
- type Node
- func ApplyJSONPath(node *Node, commands []string) (result []*Node, err error)
- func ArrayNode(key string, value []*Node) (current *Node)
- func BoolNode(key string, value bool) (current *Node)
- func Eval(node *Node, cmd string) (result *Node, err error)
- func JSONPath(data []byte, path string) (result []*Node, err error)
- func Must(root *Node, err error) *Node
- func NullNode(key string) *Node
- func NumericNode(key string, value float64) (current *Node)
- func ObjectNode(key string, value map[string]*Node) (current *Node)
- func StringNode(key string, value string) (current *Node)
- func Unmarshal(data []byte) (root *Node, err error)
- func UnmarshalSafe(data []byte) (root *Node, err error)
- func (n *Node) AppendArray(value ...*Node) error
- func (n *Node) AppendObject(key string, value *Node) error
- func (n *Node) Clone() *Node
- func (n *Node) Delete() error
- func (n *Node) DeleteIndex(index int) error
- func (n *Node) DeleteKey(key string) error
- func (n *Node) DeleteNode(value *Node) error
- func (n *Node) Empty() bool
- func (n *Node) Eq(node *Node) (result bool, err error)
- func (n *Node) Ge(node *Node) (result bool, err error)
- func (n *Node) Geq(node *Node) (result bool, err error)
- func (n *Node) GetArray() (value []*Node, err error)
- func (n *Node) GetBool() (value bool, err error)
- func (n *Node) GetIndex(index int) (*Node, error)
- func (n *Node) GetKey(key string) (*Node, error)
- func (n *Node) GetNull() (interface{}, error)
- func (n *Node) GetNumeric() (value float64, err error)
- func (n *Node) GetObject() (value map[string]*Node, err error)
- func (n *Node) GetString() (value string, err error)
- func (n *Node) HasKey(key string) bool
- func (n *Node) Index() int
- func (n *Node) Inheritors() (result []*Node)
- func (n *Node) IsArray() bool
- func (n *Node) IsBool() bool
- func (n *Node) IsDirty() bool
- func (n *Node) IsNull() bool
- func (n *Node) IsNumeric() bool
- func (n *Node) IsObject() bool
- func (n *Node) IsString() bool
- func (n *Node) JSONPath(path string) (result []*Node, err error)
- func (n *Node) Key() string
- func (n *Node) Keys() (result []string)
- func (n *Node) Le(node *Node) (result bool, err error)
- func (n *Node) Leq(node *Node) (result bool, err error)
- func (n *Node) MustArray() (value []*Node)
- func (n *Node) MustBool() (value bool)
- func (n *Node) MustIndex(index int) (value *Node)
- func (n *Node) MustKey(key string) (value *Node)
- func (n *Node) MustNull() (value interface{})
- func (n *Node) MustNumeric() (value float64)
- func (n *Node) MustObject() (value map[string]*Node)
- func (n *Node) MustString() (value string)
- func (n *Node) Neq(node *Node) (result bool, err error)
- func (n *Node) Parent() *Node
- func (n *Node) Path() string
- func (n *Node) PopIndex(index int) (node *Node, err error)
- func (n *Node) PopKey(key string) (node *Node, err error)
- func (n *Node) Set(value interface{}) error
- func (n *Node) SetArray(value []*Node) error
- func (n *Node) SetBool(value bool) error
- func (n *Node) SetNode(value *Node) error
- func (n *Node) SetNull() error
- func (n *Node) SetNumeric(value float64) error
- func (n *Node) SetObject(value map[string]*Node) error
- func (n *Node) SetString(value string) error
- func (n *Node) Size() int
- func (n *Node) Source() []byte
- func (n *Node) String() string
- func (n *Node) Type() NodeType
- func (n *Node) Unpack() (value interface{}, err error)
- func (n *Node) Value() (value interface{}, err error)
- type NodeType
- type Operation
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddConstant ¶
AddConstant add a constant for internal JSONPath script
Example ¶
AddConstant("SqrtPi", NumericNode("SqrtPi", math.SqrtPi))
Output:
Example (Eval) ¶
json := []byte(`{"radius": 50, "position": [56.4772531, 84.9918139]}`) root, err := Unmarshal(json) if err != nil { panic(err) } result, err := Eval(root, `2 * $.radius * pi`) if err != nil { panic(err) } fmt.Printf("Circumference: %0.3f m.", result.MustNumeric())
Output: Circumference: 314.159 m.
Example (Using) ¶
json := []byte(`{"foo": [true, null, false, 1, "bar", true, 1e3], "bar": [true, "baz", false]}`) result, err := JSONPath(json, `$..[?(@ == true)]`) if err != nil { panic(err) } fmt.Printf("Count of `true` values: %d", len(result))
Output: Count of `true` values: 3
func AddFunction ¶
AddFunction add a function for internal JSONPath script
Example ¶
AddFunction("array_sum", func(node *Node) (result *Node, err error) { if node.IsArray() { var ( sum, num float64 array []*Node ) array, err = node.GetArray() if err != nil { return nil, err } for _, child := range array { if !child.IsNumeric() { return nil, errors.New("wrong type") } num, err = child.GetNumeric() if err != nil { return } sum += num } return NumericNode("array_sum", sum), nil } return })
Output:
Example (Usage) ¶
json := []byte(`{"prices": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}`) root, err := Unmarshal(json) if err != nil { panic(err) } result, err := Eval(root, `avg($.prices)`) if err != nil { panic(err) } fmt.Printf("Avg price: %0.1f", result.MustNumeric())
Output: Avg price: 5.5
func AddOperation ¶
AddOperation add an operation for internal JSONPath script
Example ¶
AddOperation("<>", 3, false, func(left *Node, right *Node) (node *Node, err error) { res, err := left.Eq(right) if err != nil { return nil, err } return BoolNode("neq", !res), nil })
Output:
Example (Regex) ¶
json := []byte(`[{"name":"Foo","mail":"foo@example.com"},{"name":"bar","mail":"bar@example.org"}]`) result, err := JSONPath(json, `$.[?(@.mail =~ '.+@example\\.com')]`) if err != nil { panic(err) } fmt.Printf("JSON: %s", result[0].Source())
Output: JSON: {"name":"Foo","mail":"foo@example.com"}
func Marshal ¶ added in v0.1.0
Marshal returns slice of bytes, marshaled from current value
Example ¶
data := []byte(`[{"latitude":1,"longitude":2},{"other":"value"},null,{"internal":{"name": "unknown", "longitude":22, "latitude":11}}]`) root := Must(Unmarshal(data)) locations, _ := root.JSONPath("$..[?(@.latitude && @.longitude)]") for _, location := range locations { name := fmt.Sprintf("At [%v, %v]", location.MustKey("latitude").MustNumeric(), location.MustKey("longitude").MustNumeric()) _ = location.AppendObject("name", StringNode("", name)) } result, _ := Marshal(root) fmt.Printf("%s", result) // JSON Output: // [ // { // "latitude":1, // "longitude":2, // "name":"At [1, 2]" // }, // { // "other":"value" // }, // null, // { // "internal":{ // "name":"At [11, 22]", // "longitude":22, // "latitude":11 // } // } // ]
Output:
func ParseJSONPath ¶
ParseJSONPath will parse current path and return all commands tobe run. Example:
result, _ := ParseJSONPath("$.store.book[?(@.price < 10)].title") result == []string{"$", "store", "book", "?(@.price < 10)", "title"}
Types ¶
type ErrorType ¶
type ErrorType int
ErrorType is container for reflection type of error
const ( // WrongSymbol means that system found symbol than not allowed to be WrongSymbol ErrorType = iota // UnexpectedEOF means that data ended, leaving the node undone UnexpectedEOF // WrongType means that wrong type requested WrongType // WrongRequest means that wrong range requested WrongRequest // Unparsed means that json structure wasn't parsed yet Unparsed // UnsupportedType means that wrong type was given UnsupportedType )
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
Node is a main struct, presents any type of JSON node. Available types are:
const ( Null NodeType = iota Numeric String Bool Array Object )
Every type has its own methods to be called. Every Node contains link to a byte data, parent and children, also calculated type of value, atomic value and internal information.
func ApplyJSONPath ¶ added in v0.5.0
ApplyJSONPath function applies commands sequence parse from JSONPath. Example:
commands := []string{"$", "store", "book", "?(@.price < 10)", "title"} result, _ := ApplyJSONPath(node, commands)
Example ¶
json := `[ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ]` node := Must(Unmarshal([]byte(json))) for i := 0; i < 10; i++ { key1 := strconv.Itoa(i) key2 := strconv.Itoa(4 - i) nodes, _ := ApplyJSONPath(node, []string{"$", key1, key2}) fmt.Printf("%s", nodes) }
Output: [4][3][2][1][0][9][8][7][6][5]
func Eval ¶
Eval evaluate expression `@.price == 19.95 && @.color == 'red'` to the result value i.e. Bool(true), Numeric(3.14), etc.
Example ¶
json := []byte(`{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": [ { "color": "red", "price": 19.95 } ] } }`) root, err := Unmarshal(json) if err != nil { panic(err) } result, err := Eval(root, "avg($..price)") if err != nil { panic(err) } fmt.Print(result.MustNumeric())
Output: 14.774000000000001
func JSONPath ¶
JSONPath returns slice of founded elements in current JSON data, by it's JSONPath.
JSONPath described at http://goessner.net/articles/JsonPath/
JSONPath expressions always refer to a JSON structure in the same way as XPath expression are used in combination with an XML document. Since a JSON structure is usually anonymous and doesn't necessarily have a "root member object" JSONPath assumes the abstract name $ assigned to the outer level object.
JSONPath expressions can use the dot–notation
$.store.book[0].title
or the bracket–notation
$['store']['book'][0]['title']
for input pathes. Internal or output pathes will always be converted to the more general bracket–notation.
JSONPath allows the wildcard symbol * for member names and array indices. It borrows the descendant operator '..' from E4X and the array slice syntax proposal [start:end:step] from ECMASCRIPT 4.
Expressions of the underlying scripting language (<expr>) can be used as an alternative to explicit names or indices as in
$.store.book[(@.length-1)].title
using the symbol '@' for the current object. Filter expressions are supported via the syntax ?(<boolean expr>) as in
$.store.book[?(@.price < 10)].title
Here is a complete overview and a side by side comparison of the JSONPath syntax elements with its XPath counterparts.
$ the root object/element @ the current object/element . or [] child operator .. recursive descent. JSONPath borrows this syntax from E4X. * wildcard. All objects/elements regardless their names. [] subscript operator. XPath uses it to iterate over element collections and for predicates. In Javascript and JSON it is the native array operator. [,] Union operator in XPath results in a combination of node sets. JSONPath allows alternate names or array indices as a set. [start:end:step] array slice operator borrowed from ES4. ?() applies a filter (script) expression. () script expression, using the underlying script engine.
JSONPath Script engine ¶
Predefined constant ¶
Package has several predefined constants. You are free to add new one with AddConstant
e math.E float64 pi math.Pi float64 phi math.Phi float64 sqrt2 math.Sqrt2 float64 sqrte math.SqrtE float64 sqrtpi math.SqrtPi float64 sqrtphi math.SqrtPhi float64 ln2 math.Ln2 float64 log2e math.Log2E float64 ln10 math.Ln10 float64 log10e math.Log10E float64 true true bool false false bool null nil interface{}
Supported operations ¶
Package has several predefined operators. You are free to add new one with AddOperator
Operator precedence: https://golang.org/ref/spec#Operator_precedence
Precedence Operator 6 ** 5 * / % << >> & &^ 4 + - | ^ 3 == != < <= > >= =~ 2 && 1 ||
Arithmetic operators: https://golang.org/ref/spec#Arithmetic_operators
** power integers, floats + sum integers, floats, strings - difference integers, floats * product integers, floats / quotient integers, floats % remainder integers & bitwise AND integers | bitwise OR integers ^ bitwise XOR integers &^ bit clear (AND NOT) integers << left shift integer << unsigned integer >> right shift integer >> unsigned integer == equals any != not equals any < less any <= less or equals any > larger any >= larger or equals any =~ equals regex string strings
Supported functions ¶
Package has several predefined functions. You are free to add new one with AddFunction
abs math.Abs integers, floats acos math.Acos integers, floats acosh math.Acosh integers, floats asin math.Asin integers, floats asinh math.Asinh integers, floats atan math.Atan integers, floats atanh math.Atanh integers, floats avg Average array of integers or floats cbrt math.Cbrt integers, floats ceil math.Ceil integers, floats cos math.Cos integers, floats cosh math.Cosh integers, floats erf math.Erf integers, floats erfc math.Erfc integers, floats erfcinv math.Erfcinv integers, floats erfinv math.Erfinv integers, floats exp math.Exp integers, floats exp2 math.Exp2 integers, floats expm1 math.Expm1 integers, floats factorial N! unsigned integer floor math.Floor integers, floats gamma math.Gamma integers, floats j0 math.J0 integers, floats j1 math.J1 integers, floats length len array log math.Log integers, floats log10 math.Log10 integers, floats log1p math.Log1p integers, floats log2 math.Log2 integers, floats logb math.Logb integers, floats not not any pow10 math.Pow10 integer round math.Round integers, floats roundtoeven math.RoundToEven integers, floats sin math.Sin integers, floats sinh math.Sinh integers, floats sqrt math.Sqrt integers, floats tan math.Tan integers, floats tanh math.Tanh integers, floats trunc math.Trunc integers, floats y0 math.Y0 integers, floats y1 math.Y1 integers, floats
Example ¶
json := []byte(`{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } }`) authors, err := JSONPath(json, "$.store.book[*].author") if err != nil { panic(err) } for _, author := range authors { fmt.Println(author.MustString()) }
Output: Nigel Rees Evelyn Waugh Herman Melville J. R. R. Tolkien
Example (Array) ¶
json := []byte(`{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } }`) authors, err := JSONPath(json, "$.store.book[*].author") if err != nil { panic(err) } result, err := Marshal(ArrayNode("", authors)) if err != nil { panic(err) } fmt.Println(string(result))
Output: ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
func Must ¶ added in v0.1.0
Must returns a Node if there was no error. Else - panic with error as the value.
Example ¶
data := []byte(`{ "Image": { "Width": 800, "Height": 600, "Title": "View from 15th Floor", "Thumbnail": { "Url": "http://www.example.com/image/481989943", "Height": 125, "Width": 100 }, "Animated" : false, "IDs": [116, 943, 234, 38793] } }`) root := Must(Unmarshal(data)) fmt.Printf("Object has %d inheritors inside", root.Size())
Output: Object has 1 inheritors inside
Example (Panic) ¶
defer func() { if rec := recover(); rec != nil { fmt.Printf("Unmarshal(): %s", rec) } }() data := []byte(`{]`) root := Must(Unmarshal(data)) fmt.Printf("Object has %d inheritors inside", root.Size())
Output: Unmarshal(): wrong symbol ']' at 1
func NumericNode ¶
NumericNode is constructor for Node with a Numeric value
func ObjectNode ¶
ObjectNode is constructor for Node with an Object value
func StringNode ¶
StringNode is constructor for Node with a String value
func Unmarshal ¶
Unmarshal parses the JSON-encoded data and return the root node of struct.
Doesn't calculate values, just type of stored value. It will store link to the data, on all life long.
Example ¶
Calculate AVG price from different types of objects, JSON from: https://goessner.net/articles/JsonPath/index.html#e3
data := []byte(`{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 }, "tools": null } }`) root, err := Unmarshal(data) if err != nil { panic(err) } store := root.MustKey("store").MustObject() var prices float64 size := 0 for _, objects := range store { if objects.IsArray() && objects.Size() > 0 { size += objects.Size() for _, object := range objects.MustArray() { prices += object.MustKey("price").MustNumeric() } } else if objects.IsObject() && objects.HasKey("price") { size++ prices += objects.MustKey("price").MustNumeric() } } if size > 0 { fmt.Println("AVG price:", prices/float64(size)) } else { fmt.Println("AVG price:", 0) }
Output:
Example (Unpack) ¶
Unpack object interface and render html link. JSON from: https://tools.ietf.org/html/rfc7159#section-13
data := []byte(`{ "Image": { "Width": 800, "Height": 600, "Title": "View from 15th Floor", "Thumbnail": { "Url": "http://www.example.com/image/481989943", "Height": 125, "Width": 100 }, "Animated" : false, "IDs": [116, 943, 234, 38793] } }`) root, err := Unmarshal(data) if err != nil { panic(err) } object, err := root.Unpack() if err != nil { panic(err) } image := object.(map[string]interface{})["Image"].(map[string]interface{}) thumbnail := image["Thumbnail"].(map[string]interface{}) fmt.Printf( `<a href="%s?width=%.0f&height=%.0f" title="%s"><img src="%s?width=%.0f&height=%.0f" /></a>`, thumbnail["Url"], image["Width"], image["Height"], image["Title"], thumbnail["Url"], thumbnail["Width"], thumbnail["Height"], )
Output:
func UnmarshalSafe ¶
UnmarshalSafe do the same thing as Unmarshal, but copy data to the local variable, to make it editable.
func (*Node) AppendArray ¶ added in v0.1.0
AppendArray appends current Array node values with Node values
func (*Node) AppendObject ¶ added in v0.1.0
AppendObject appends current Object node value with key:value
func (*Node) Clone ¶ added in v0.4.0
Clone creates full copy of current Node. With all child, but without link to the parent.
Example ¶
root := Must(Unmarshal(jsonPathTestData)) nodes, _ := root.JSONPath("$..price") for i, node := range nodes { nodes[i] = node.Clone() } result, _ := Marshal(ArrayNode("", nodes)) fmt.Printf("Array: %s\n", result) result, _ = Marshal(root) fmt.Printf("Basic: %s\n", result)
Output: Array: [19.95,8.95,12.99,8.99,22.99] Basic: { "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } }
func (*Node) DeleteIndex ¶ added in v0.1.0
DeleteIndex removes element from Array, by it's index
func (*Node) DeleteNode ¶ added in v0.1.0
DeleteNode removes element child
func (*Node) GetIndex ¶
GetIndex will return child node of current array node. If current node is not Array, or index is unavailable, will return error
func (*Node) GetKey ¶
GetKey will return child node of current object node. If current node is not Object, or key is unavailable, will return error
func (*Node) GetNumeric ¶
GetNumeric returns float64, if current type is Numeric, else: WrongType error
func (*Node) GetObject ¶
GetObject returns map[string]*Node, if current type is Object, else: WrongType error
func (*Node) Index ¶
Index will return index of current node, please check, that parent of this node has an Array type
func (*Node) Inheritors ¶
Inheritors return sorted by keys/index slice of children
func (*Node) Key ¶
Key will return key of current node, please check, that parent of this node has an Object type
func (*Node) Keys ¶
Keys will return count all keys of children of current node, please check, that parent of this node has an Object type
func (*Node) MustArray ¶
MustArray returns []*Node, if current type is Array, else: panic if error happened
func (*Node) MustBool ¶
MustBool returns bool, if current type is Bool, else: panic if error happened
func (*Node) MustIndex ¶
MustIndex will return child node of current array node. If current node is not Array, or index is unavailable, raise a panic
func (*Node) MustKey ¶
MustKey will return child node of current object node. If current node is not Object, or key is unavailable, raise a panic
func (*Node) MustNull ¶
func (n *Node) MustNull() (value interface{})
MustNull returns nil, if current type is Null, else: panic if error happened
func (*Node) MustNumeric ¶
MustNumeric returns float64, if current type is Numeric, else: panic if error happened
func (*Node) MustObject ¶
MustObject returns map[string]*Node, if current type is Object, else: panic if error happened
func (*Node) MustString ¶
MustString returns string, if current type is String, else: panic if error happened
func (*Node) PopIndex ¶ added in v0.1.0
PopIndex removes element from Array, by it's index and return it
func (*Node) SetNode ¶ added in v0.6.0
SetNode updates current node value with the clone of the given Node value NB! The result will be the clone of the given Node!
func (*Node) SetNumeric ¶ added in v0.1.0
SetNumeric updates current node value with Numeric value
func (*Node) Size ¶
Size will return count of children of current node, please check, that parent of this node has an Array type
func (*Node) String ¶
String is implementation of Stringer interface, returns string based on source part
func (*Node) Unpack ¶
Unpack will produce current node to it's interface, recursively with all underlying nodes (in contrast to Node.Value).
func (*Node) Value ¶
Value is calculating and returns a value of current node.
It returns nil, if current node type is Null.
It returns float64, if current node type is Numeric.
It returns string, if current node type is String.
It returns bool, if current node type is Bool.
It returns []*Node, if current node type is Array.
It returns map[string]*Node, if current node type is Object.
BUT! Current method doesn't calculate underlying nodes (use method Node.Unpack for that).
Value will be calculated only once and saved into atomic.Value.
type NodeType ¶
type NodeType int32
NodeType is a kind of reflection of JSON type to a type of golang
const ( // Null is reflection of nil.(interface{}) Null NodeType = iota // Numeric is reflection of float64 Numeric // String is reflection of string String // Bool is reflection of bool Bool // Array is reflection of []*Node Array // Object is reflection of map[string]*Node Object )
Reflections:
Null = nil.(interface{}) Numeric = float64 String = string Bool = bool Array = []*Node Object = map[string]*Node
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
cmd
|
|
Copy from https://github.com/freddierice/php_source/blob/467ed5d6edff72219afd3e644516f131118ef48e/ext/json/JSON_parser.c Base code: Copyright (c) 2005 JSON.org
|
Copy from https://github.com/freddierice/php_source/blob/467ed5d6edff72219afd3e644516f131118ef48e/ext/json/JSON_parser.c Base code: Copyright (c) 2005 JSON.org |