forked from mirror/gjson
sped up map[string]interface{} unmarshalling
This commit is contained in:
parent
0669befdc3
commit
67e38154bd
71
gjson.go
71
gjson.go
|
@ -100,7 +100,7 @@ func (t Result) Array() []Result {
|
||||||
if t.Type != JSON {
|
if t.Type != JSON {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
a, _, _ := t.arrayOrMap('[')
|
a, _, _, _, _ := t.arrayOrMap('[', false)
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ func (t Result) Map() map[string]Result {
|
||||||
if t.Type != JSON {
|
if t.Type != JSON {
|
||||||
return map[string]Result{}
|
return map[string]Result{}
|
||||||
}
|
}
|
||||||
_, o, _ := t.arrayOrMap('{')
|
_, _, o, _, _ := t.arrayOrMap('{', false)
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,9 +119,17 @@ func (t Result) Get(path string) Result {
|
||||||
return Get(t.Raw, path)
|
return Get(t.Raw, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Result) arrayOrMap(vc byte) ([]Result, map[string]Result, byte) {
|
func (t Result) arrayOrMap(vc byte, valueize bool) (
|
||||||
var a = []Result{}
|
[]Result,
|
||||||
var o = map[string]Result{}
|
[]interface{},
|
||||||
|
map[string]Result,
|
||||||
|
map[string]interface{},
|
||||||
|
byte,
|
||||||
|
) {
|
||||||
|
var a []Result
|
||||||
|
var ai []interface{}
|
||||||
|
var o map[string]Result
|
||||||
|
var oi map[string]interface{}
|
||||||
var json = t.Raw
|
var json = t.Raw
|
||||||
var i int
|
var i int
|
||||||
var value Result
|
var value Result
|
||||||
|
@ -149,6 +157,19 @@ func (t Result) arrayOrMap(vc byte) ([]Result, map[string]Result, byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if vc == '{' {
|
||||||
|
if valueize {
|
||||||
|
oi = make(map[string]interface{})
|
||||||
|
} else {
|
||||||
|
o = make(map[string]Result)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if valueize {
|
||||||
|
ai = make([]interface{}, 0)
|
||||||
|
} else {
|
||||||
|
a = make([]Result, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
for ; i < len(json); i++ {
|
for ; i < len(json); i++ {
|
||||||
if json[i] <= ' ' {
|
if json[i] <= ' ' {
|
||||||
continue
|
continue
|
||||||
|
@ -187,21 +208,34 @@ func (t Result) arrayOrMap(vc byte) ([]Result, map[string]Result, byte) {
|
||||||
if count%2 == 0 {
|
if count%2 == 0 {
|
||||||
key = value
|
key = value
|
||||||
} else {
|
} else {
|
||||||
o[key.Str] = value
|
if valueize {
|
||||||
|
oi[key.Str] = value.Value()
|
||||||
|
} else {
|
||||||
|
o[key.Str] = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
} else {
|
} else {
|
||||||
a = append(a, value)
|
if valueize {
|
||||||
|
ai = append(ai, value.Value())
|
||||||
|
} else {
|
||||||
|
a = append(a, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
return a, o, vc
|
return a, ai, o, oi, vc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses the json and returns a result
|
// Parse parses the json and returns a result
|
||||||
func Parse(json string) Result {
|
func Parse(json string) Result {
|
||||||
var value Result
|
var value Result
|
||||||
for i := 0; i < len(json); i++ {
|
for i := 0; i < len(json); i++ {
|
||||||
|
if json[i] == '{' || json[i] == '[' {
|
||||||
|
value.Type = JSON
|
||||||
|
value.Raw = json[i:] // just take the entire raw
|
||||||
|
break
|
||||||
|
}
|
||||||
if json[i] <= ' ' {
|
if json[i] <= ' ' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -213,13 +247,6 @@ func Parse(json string) Result {
|
||||||
} else {
|
} else {
|
||||||
return Result{}
|
return Result{}
|
||||||
}
|
}
|
||||||
case '{', '[':
|
|
||||||
value.Type = JSON
|
|
||||||
value.Raw = json[i:]
|
|
||||||
// we just trim the tail end
|
|
||||||
for value.Raw[len(value.Raw)-1] <= ' ' {
|
|
||||||
value.Raw = value.Raw[:len(value.Raw)-1]
|
|
||||||
}
|
|
||||||
case 'n':
|
case 'n':
|
||||||
value.Type = Null
|
value.Type = Null
|
||||||
value.Raw = tolit(json[i:])
|
value.Raw = tolit(json[i:])
|
||||||
|
@ -390,19 +417,11 @@ func (t Result) Value() interface{} {
|
||||||
case Number:
|
case Number:
|
||||||
return t.Num
|
return t.Num
|
||||||
case JSON:
|
case JSON:
|
||||||
a, o, vc := t.arrayOrMap(0)
|
_, ai, _, oi, vc := t.arrayOrMap(0, true)
|
||||||
if vc == '{' {
|
if vc == '{' {
|
||||||
var m = map[string]interface{}{}
|
return oi
|
||||||
for k, v := range o {
|
|
||||||
m[k] = v.Value()
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
} else if vc == '[' {
|
} else if vc == '[' {
|
||||||
var m = make([]interface{}, 0, len(a))
|
return ai
|
||||||
for _, v := range a {
|
|
||||||
m = append(m, v.Value())
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case True:
|
case True:
|
||||||
|
|
|
@ -395,6 +395,33 @@ func BenchmarkGJSONGet(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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkGJSONUnmarshalMap(t *testing.B) {
|
||||||
|
t.ReportAllocs()
|
||||||
|
for i := 0; i < t.N; i++ {
|
||||||
|
for j := 0; j < len(benchPaths); j++ {
|
||||||
|
parts := strings.Split(benchPaths[j], ".")
|
||||||
|
m := Parse(exampleJSON).Value().(map[string]interface{})
|
||||||
|
var v interface{}
|
||||||
|
for len(parts) > 0 {
|
||||||
|
part := parts[0]
|
||||||
|
if len(parts) > 1 {
|
||||||
|
m = m[part].(map[string]interface{})
|
||||||
|
if m == nil {
|
||||||
|
t.Fatal("did not find the value")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v = m[part]
|
||||||
|
if v == nil {
|
||||||
|
t.Fatal("did not find the value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parts = parts[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.N *= len(benchPaths) // because we are running against 3 paths
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkJSONUnmarshalMap(t *testing.B) {
|
func BenchmarkJSONUnmarshalMap(t *testing.B) {
|
||||||
t.ReportAllocs()
|
t.ReportAllocs()
|
||||||
for i := 0; i < t.N; i++ {
|
for i := 0; i < t.N; i++ {
|
||||||
|
|
Loading…
Reference in New Issue