mirror of https://github.com/tidwall/gjson.git
added direct bytes interface
This commit is contained in:
parent
b7e578ec72
commit
124a25db9e
21
gjson.go
21
gjson.go
|
@ -3,6 +3,7 @@ package gjson
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/tidwall/match"
|
"github.com/tidwall/match"
|
||||||
)
|
)
|
||||||
|
@ -1080,6 +1081,11 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
return i, false
|
return i, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type parseContext struct {
|
||||||
|
json string
|
||||||
|
value Result
|
||||||
|
}
|
||||||
|
|
||||||
// Get searches json for the specified path.
|
// Get searches json for the specified path.
|
||||||
// A path is in dot syntax, such as "name.last" or "age".
|
// A path is in dot syntax, such as "name.last" or "age".
|
||||||
// This function expects that the json is well-formed, and does not validate.
|
// This function expects that the json is well-formed, and does not validate.
|
||||||
|
@ -1127,9 +1133,18 @@ func Get(json, path string) Result {
|
||||||
return c.value
|
return c.value
|
||||||
}
|
}
|
||||||
|
|
||||||
type parseContext struct {
|
// GetBytes searches json for the specified path.
|
||||||
json string
|
// If working with bytes, this method preferred over Get(string(data), path)
|
||||||
value Result
|
func GetBytes(json []byte, path string) Result {
|
||||||
|
var result Result
|
||||||
|
if json != nil {
|
||||||
|
// unsafe cast to string
|
||||||
|
result = Get(*(*string)(unsafe.Pointer(&json)), path)
|
||||||
|
// copy of string data for safety
|
||||||
|
result.Raw = string(*(*[]byte)(unsafe.Pointer(&result.Raw)))
|
||||||
|
result.Str = string(*(*[]byte)(unsafe.Pointer(&result.Str)))
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// unescape unescapes a string
|
// unescape unescapes a string
|
||||||
|
|
|
@ -35,7 +35,7 @@ func TestRandomData(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
lstr = string(b[:n])
|
lstr = string(b[:n])
|
||||||
Get(lstr, "zzzz")
|
GetBytes([]byte(lstr), "zzzz")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +125,21 @@ var basicJSON = `{"age":100, "name":{"here":"B\\\"R"},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
var basicJSONB = []byte(basicJSON)
|
||||||
|
|
||||||
|
func TestByteSafety(t *testing.T) {
|
||||||
|
jsonb := []byte(`{"name":"Janet"}`)
|
||||||
|
mtok := GetBytes(jsonb, "name")
|
||||||
|
if mtok.String() != "Janet" {
|
||||||
|
t.Fatalf("expected %v, got %v", "Jason", mtok.String())
|
||||||
|
}
|
||||||
|
jsonb[9] = 'T'
|
||||||
|
jsonb[12] = 'd'
|
||||||
|
jsonb[13] = 'y'
|
||||||
|
if mtok.String() != "Janet" {
|
||||||
|
t.Fatalf("expected %v, got %v", "Jason", mtok.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBasic(t *testing.T) {
|
func TestBasic(t *testing.T) {
|
||||||
var mtok Result
|
var mtok Result
|
||||||
|
@ -134,6 +149,11 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("expected %v, got %v", "1002,3", mtok.String())
|
t.Fatalf("expected %v, got %v", "1002,3", mtok.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mtok = GetBytes(basicJSONB, `loggy.programmers.#[age=101].firstName`)
|
||||||
|
if mtok.String() != "1002.3" {
|
||||||
|
t.Fatalf("expected %v, got %v", "1002,3", mtok.String())
|
||||||
|
}
|
||||||
|
|
||||||
mtok = Get(basicJSON, `loggy.programmers.#[firstName == "Brett"].email`)
|
mtok = Get(basicJSON, `loggy.programmers.#[firstName == "Brett"].email`)
|
||||||
if mtok.String() != "aaaa" {
|
if mtok.String() != "aaaa" {
|
||||||
t.Fatalf("expected %v, got %v", "aaaa", mtok.String())
|
t.Fatalf("expected %v, got %v", "aaaa", mtok.String())
|
||||||
|
@ -740,3 +760,41 @@ func BenchmarkJSONParserGet(t *testing.B) {
|
||||||
}
|
}
|
||||||
t.N *= len(benchPaths) // because we are running against 3 paths
|
t.N *= len(benchPaths) // because we are running against 3 paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var massiveJSON = func() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.WriteString("[")
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteByte(',')
|
||||||
|
}
|
||||||
|
buf.WriteString(exampleJSON)
|
||||||
|
}
|
||||||
|
buf.WriteString("]")
|
||||||
|
return buf.String()
|
||||||
|
}()
|
||||||
|
|
||||||
|
func BenchmarkConvertNone(t *testing.B) {
|
||||||
|
json := massiveJSON
|
||||||
|
t.ReportAllocs()
|
||||||
|
t.ResetTimer()
|
||||||
|
for i := 0; i < t.N; i++ {
|
||||||
|
Get(json, "50.widget.text.onMouseUp")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func BenchmarkConvertGet(t *testing.B) {
|
||||||
|
data := []byte(massiveJSON)
|
||||||
|
t.ReportAllocs()
|
||||||
|
t.ResetTimer()
|
||||||
|
for i := 0; i < t.N; i++ {
|
||||||
|
Get(string(data), "50.widget.text.onMouseUp")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func BenchmarkConvertGetBytes(t *testing.B) {
|
||||||
|
data := []byte(massiveJSON)
|
||||||
|
t.ReportAllocs()
|
||||||
|
t.ResetTimer()
|
||||||
|
for i := 0; i < t.N; i++ {
|
||||||
|
GetBytes(data, "50.widget.text.onMouseUp")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue