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 (
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/tidwall/match"
|
||||
)
|
||||
|
@ -1080,6 +1081,11 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
return i, false
|
||||
}
|
||||
|
||||
type parseContext struct {
|
||||
json string
|
||||
value Result
|
||||
}
|
||||
|
||||
// Get searches json for the specified path.
|
||||
// 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.
|
||||
|
@ -1127,9 +1133,18 @@ func Get(json, path string) Result {
|
|||
return c.value
|
||||
}
|
||||
|
||||
type parseContext struct {
|
||||
json string
|
||||
value Result
|
||||
// GetBytes searches json for the specified path.
|
||||
// If working with bytes, this method preferred over Get(string(data), path)
|
||||
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
|
||||
|
|
|
@ -35,7 +35,7 @@ func TestRandomData(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
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) {
|
||||
var mtok Result
|
||||
|
@ -134,6 +149,11 @@ func TestBasic(t *testing.T) {
|
|||
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`)
|
||||
if mtok.String() != "aaaa" {
|
||||
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
|
||||
}
|
||||
|
||||
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