jsonpath

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 7, 2020 License: MIT Imports: 8 Imported by: 9

README

JSONPath

Build Status Go Report Card Coverage Status

This is Go package providing the features that retrieves a part of the JSON objects according to the statement written in the JSONPath syntax.

The core syntaxes of the JSONPath on which this package is based: JSONPath - XPath for JSON.

Note:

The unstated syntaxes found in "JSONPath - XPath for JSON" are implemented with reference to the test cases written in cburmer's json-path-comparison. Please check my compare result to know which responses are adapted. Unfortunately, the proposals that is also discussing in "json-path-comparison" were not finalized at the start of development and were not adopted outright.

Getting started

go get github.com/AsaiYusuke/jsonpath
Simple example:
package main

import (
	"encoding/json"
	"fmt"

	"github.com/AsaiYusuke/jsonpath"
)

func main() {
	jsonPath, srcJSON := `$.key`, `{"key":"value"}`
	var src interface{}
	json.Unmarshal([]byte(srcJSON), &src)
	output, _ := jsonpath.Retrieve(jsonPath, src)
	outputJSON, _ := json.Marshal(output)
	fmt.Println(string(outputJSON))
	// Output:
	// ["value"]
}

Basic design

  • PEG separated the JSONPath syntax analyzer from functionality itself to simplify the source.
  • The error specification allows package users to handle errors appropriately.
  • Adopted more of the consensus behavior from the cburmer's json-path-comparison. Adapted my own behavior to the other part of the such consensus behavior that found difficult to use.
  • Equipped with numerous unit tests and tried to eliminate the bugs that return strange result.

How to use

* Retrieve one-time, or successively

The Retrieve function returns a retrieved JSON object by a one-time sequential operation (analyzing syntax and retrieving objects) using the given JSONPath and the source JSON object :

output, err := jsonpath.Retrieve(jsonPath, src)

The Parse function returns a parser-function that completed to analyze the JSONPath syntax. By using this returned parser-function it can be performed successively a retrieve with the same JSONPath syntax :

jsonPath, err := jsonpath.Parse(jsonPath)
output1, err1 := jsonPath(src1)
output2, err2 := jsonPath(src2)
:
* Error handling

If there is a problem with the execution of the Retrieve, Prepare or prepared parser-functions, an error type is returned. These error types define the corresponding symptom, as listed below:

Syntax analyze errors from Retrieve, Parse
Error type Message format Symptom
ErrorInvalidSyntax invalid syntax (position=%d, reason=%s, near=%s) The invalid syntax found in the JSONPath. The reason including in this message will tell you more about it.
ErrorInvalidArgument invalid argument (argument=%s, error=%s) The argument specified in the JSONPath was treated as the invalid error in Go syntax.
ErrorNotSupported not supported (feature=%s, path=%s) The unsupported syntaxes specified in the JSONPath.
Runtime errors from Retrieve, parser-functions
Error type Message format Symptom
ErrorMemberNotExist member did not exist (path=%s) The object member specified in the JSONPath did not exist in the JSON object.
ErrorIndexOutOfRange index out of range (path=%s) The array indexes specified in the JSONPath were out of range.
ErrorTypeUnmatched type unmatched (expected=%s, found=%s, path=%s) The node type specified in the JSONPath did not exist in the JSON object.
ErrorNoneMatched none matched (path=%s) The retrieving child paths specified in the JSONPath resulted in empty output.

The type checking is convenient to recognize which error happened.

:
_,err := jsonpath.Retrieve(jsonPath, srcJSON)
if err != nil {
  switch err.(type) {
  case jsonpath.ErrorIndexOutOfRange:
    fmt.printf(`retry with other srcJSON: %v`, err)
    continue
  case jsonpath.ErrorInvalidArgumentFormat:
    return nil, fmt.errorf(`specified invalid argument: %v`, err)
  }
  :
}

Differences

Some behaviors that differ from the consensus exists in this package. For the entire comparisons, please check this result to see which responses are different.

Character types

The character types that can not be used for the identifiers in the dot notation are as follows :

. [ ) = ! > < \t \r \n *SPACE*

You have to encode these characters when you enter them :

JSONPath : $.abc\.def
srcJSON  : {"abc.def":1}
Output   : 1
Asterisk in qualifier

The asterisk in qualifier can be specified mixed with other subscript syntaxes.

JSONPath : $[0,1:3,*]
srcJSON  : [0,1,2,3,4,5]
Output   : [0,1,2,0,1,2,3,4,5]
Regular expression

The regular expression syntax works as a regular expression in Go lang. In particular, you can use "(?i)" to specify the regular expression as the ignore case option.

JSONPath : $[?(@.a=~/(?i)CASE/)]
srcJSON  : ["Case","Hello"]
Output   : ["Case"]

Benchmarks

Show results
goos: windows
goarch: amd64
pkg: github.com/AsaiYusuke/jsonpath
BenchmarkRetrieve_dotNotation-4                             	   11354	     98725 ns/op	  533608 B/op	     146 allocs/op
BenchmarkRetrieve_bracketNotation-4                         	   10000	    119519 ns/op	  533623 B/op	     147 allocs/op
BenchmarkRetrieve_asterisk_identifier_dotNotation-4         	   10000	    105806 ns/op	  533651 B/op	     148 allocs/op
BenchmarkRetrieve_asterisk_identifier_bracketNotation-4     	   10000	    118763 ns/op	  533592 B/op	     146 allocs/op
BenchmarkRetrieve_multi_identifier-4                        	    8020	    129579 ns/op	  533902 B/op	     157 allocs/op
BenchmarkRetrieve_qualifier_index-4                         	   10000	    114525 ns/op	  533598 B/op	     148 allocs/op
BenchmarkRetrieve_qualifier_slice-4                         	    9230	    120536 ns/op	  533805 B/op	     152 allocs/op
BenchmarkRetrieve_qualifier_asterisk-4                      	   10000	    108871 ns/op	  533561 B/op	     146 allocs/op
BenchmarkRetrieve_qualifier_union-4                         	   10000	    123751 ns/op	  533890 B/op	     159 allocs/op
BenchmarkRetrieve_filter_logicalOR-4                        	    9246	    134633 ns/op	  534613 B/op	     161 allocs/op
BenchmarkRetrieve_filter_logicalAND-4                       	   10000	    132457 ns/op	  534869 B/op	     163 allocs/op
BenchmarkRetrieve_filter_nodeFilter-4                       	    9250	    125146 ns/op	  534417 B/op	     161 allocs/op
BenchmarkRetrieve_filter_logicalNOT-4                       	    9256	    133314 ns/op	  534485 B/op	     164 allocs/op
BenchmarkRetrieve_filter_compareEQ-4                        	    8593	    143504 ns/op	  535122 B/op	     171 allocs/op
BenchmarkRetrieve_filter_compareNE-4                        	    9252	    141937 ns/op	  534932 B/op	     171 allocs/op
BenchmarkRetrieve_filter_compareGE-4                        	    8594	    143957 ns/op	  535120 B/op	     171 allocs/op
BenchmarkRetrieve_filter_compareGT-4                        	    8592	    142375 ns/op	  535013 B/op	     170 allocs/op
BenchmarkRetrieve_filter_compareLE-4                        	    8593	    143808 ns/op	  535106 B/op	     170 allocs/op
BenchmarkRetrieve_filter_compareLT-4                        	    9255	    142373 ns/op	  535007 B/op	     169 allocs/op
BenchmarkRetrieve_filter_regex-4                            	    7519	    147486 ns/op	  543410 B/op	     183 allocs/op
BenchmarkParserFunc_dotNotation-4                           	 9400027	       126 ns/op	      48 B/op	       2 allocs/op
BenchmarkParserFunc_bracketNotation-4                       	 9473965	       126 ns/op	      48 B/op	       2 allocs/op
BenchmarkParserFunc_asterisk_identifier_dotNotation-4       	 4282303	       277 ns/op	      96 B/op	       4 allocs/op
BenchmarkParserFunc_asterisk_identifier_bracketNotation-4   	 4198162	       286 ns/op	      96 B/op	       4 allocs/op
BenchmarkParserFunc_multi_identifier-4                      	 5104863	       238 ns/op	      80 B/op	       3 allocs/op
BenchmarkParserFunc_qualifier_index-4                       	 6780312	       178 ns/op	      64 B/op	       4 allocs/op
BenchmarkParserFunc_qualifier_slice-4                       	 5805200	       207 ns/op	      64 B/op	       4 allocs/op
BenchmarkParserFunc_qualifier_asterisk-4                    	 6585810	       178 ns/op	      64 B/op	       4 allocs/op
BenchmarkParserFunc_qualifier_union-4                       	 3584234	       335 ns/op	     120 B/op	       7 allocs/op
BenchmarkParserFunc_filter_logicalOR-4                      	  999666	      1184 ns/op	     912 B/op	      12 allocs/op
BenchmarkParserFunc_filter_logicalAND-4                     	  858484	      1364 ns/op	    1168 B/op	      14 allocs/op
BenchmarkParserFunc_filter_nodeFilter-4                     	 1594872	       741 ns/op	     608 B/op	       8 allocs/op
BenchmarkParserFunc_filter_logicalNOT-4                     	 1218441	       974 ns/op	     656 B/op	      10 allocs/op
BenchmarkParserFunc_filter_compareEQ-4                      	  925389	      1328 ns/op	    1120 B/op	      12 allocs/op
BenchmarkParserFunc_filter_compareNE-4                      	 1000000	      1217 ns/op	     912 B/op	      11 allocs/op
BenchmarkParserFunc_filter_compareGE-4                      	  940814	      1242 ns/op	    1120 B/op	      12 allocs/op
BenchmarkParserFunc_filter_compareGT-4                      	 1000000	      1242 ns/op	    1120 B/op	      12 allocs/op
BenchmarkParserFunc_filter_compareLE-4                      	  933510	      1232 ns/op	    1120 B/op	      12 allocs/op
BenchmarkParserFunc_filter_compareLT-4                      	  859462	      1247 ns/op	    1120 B/op	      12 allocs/op
BenchmarkParserFunc_filter_regex-4                          	  801913	      1431 ns/op	    1137 B/op	      13 allocs/op

Project progress

  • syntax
    • identifier
      • identifier in dot notations
      • identifier in bracket notations
      • asterisk identifier
      • multiple-identifier in bracket
      • recursive retrieve
    • qualifier
      • index
      • slice
      • asterisk
      • filter
        • logical operation
        • comparator
        • JSONPath retrieve in filter
      • script
    • Refer to the consensus behaviors
  • archtecture
    • PEG syntax analyzing
    • Error handling
  • Go language manner
    • retrieve with the object in interface unmarshal
    • retrieve with the json.Number type
  • source code
    • Release version
    • Unit tests
      • syntax tests
      • benchmark
      • coverage >80%
    • Examples
    • CI automation
    • Documentation
      • README
      • API doc
    • comparison result (local)
  • future todo
    • Syntax expansion
    • Refer to the something standard
    • Go language affinity
      • retrieve with the object in struct unmarshal
      • retrieve with the struct tags
      • retrieve with the user defined objects

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Parse

func Parse(jsonPath string) (func(src interface{}) ([]interface{}, error), error)

Parse returns the parser function using the given JSONPath.

func Retrieve

func Retrieve(jsonPath string, src interface{}) ([]interface{}, error)

Retrieve returns the retrieved JSON using the given JSONPath.

Types

type ErrorIndexOutOfRange

type ErrorIndexOutOfRange struct {
	// contains filtered or unexported fields
}

ErrorIndexOutOfRange represents the error that the array indexes specified in the JSONPath are out of range.

func (ErrorIndexOutOfRange) Error

func (e ErrorIndexOutOfRange) Error() string

type ErrorInvalidArgument

type ErrorInvalidArgument struct {
	// contains filtered or unexported fields
}

ErrorInvalidArgument represents the error that argument specified in the JSONPath is treated as the invalid error in Go syntax.

func (ErrorInvalidArgument) Error

func (e ErrorInvalidArgument) Error() string

type ErrorInvalidSyntax

type ErrorInvalidSyntax struct {
	// contains filtered or unexported fields
}

ErrorInvalidSyntax represents the error that have syntax error in the JSONPath.

func (ErrorInvalidSyntax) Error

func (e ErrorInvalidSyntax) Error() string

type ErrorMemberNotExist

type ErrorMemberNotExist struct {
	// contains filtered or unexported fields
}

ErrorMemberNotExist represents the error that the object member specified in the JSONPath did not exist in the JSON object.

func (ErrorMemberNotExist) Error

func (e ErrorMemberNotExist) Error() string

type ErrorNoneMatched

type ErrorNoneMatched struct {
	// contains filtered or unexported fields
}

ErrorNoneMatched represents the error that the child paths specified in the JSONPath result in empty output.

func (ErrorNoneMatched) Error

func (e ErrorNoneMatched) Error() string

type ErrorNotSupported

type ErrorNotSupported struct {
	// contains filtered or unexported fields
}

ErrorNotSupported represents the error that the unsupported syntaxes specified in the JSONPath.

func (ErrorNotSupported) Error

func (e ErrorNotSupported) Error() string

type ErrorTypeUnmatched

type ErrorTypeUnmatched struct {
	// contains filtered or unexported fields
}

ErrorTypeUnmatched represents the error that the node type specified in the JSONPath did not exist in the JSON object.

func (ErrorTypeUnmatched) Error

func (e ErrorTypeUnmatched) Error() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL