@@ -11,13 +11,14 @@ import (
11
11
12
12
// Errors
13
13
var (
14
- KeyPathNotFoundError = errors .New ("Key path not found" )
14
+ KeyPathNotFoundError = errors .New ("Key path not found" )
15
15
UnknownValueTypeError = errors .New ("Unknown value type" )
16
- MalformedJsonError = errors .New ("Malformed JSON error" )
17
- MalformedStringError = errors .New ("Value is string, but can't find closing '\" ' symbol" )
18
- MalformedArrayError = errors .New ("Value is array, but can't find closing ']' symbol" )
19
- MalformedObjectError = errors .New ("Value looks like object, but can't find closing '}' symbol" )
20
- MalformedValueError = errors .New ("Value looks like Number/Boolean/None, but can't find its end: ',' or '}' symbol" )
16
+ MalformedJsonError = errors .New ("Malformed JSON error" )
17
+ MalformedStringError = errors .New ("Value is string, but can't find closing '\" ' symbol" )
18
+ MalformedArrayError = errors .New ("Value is array, but can't find closing ']' symbol" )
19
+ MalformedObjectError = errors .New ("Value looks like object, but can't find closing '}' symbol" )
20
+ MalformedValueError = errors .New ("Value looks like Number/Boolean/None, but can't find its end: ',' or '}' symbol" )
21
+ NotAPrimitiveError = errors .New ("Cannot parse a non-primitive value in ParsePrimitiveValue" )
21
22
)
22
23
23
24
func tokenEnd (data []byte ) int {
@@ -31,7 +32,6 @@ func tokenEnd(data []byte) int {
31
32
return - 1
32
33
}
33
34
34
-
35
35
// Find position of next character which is not ' ', ',', '}' or ']'
36
36
func nextToken (data []byte , skipComma bool ) int {
37
37
for i , c := range data {
@@ -133,10 +133,10 @@ func searchKeys(data []byte, keys ...string) int {
133
133
i += valueOffset
134
134
135
135
// if string is a Key, and key level match
136
- if data [i ] == ':' {
136
+ if data [i ] == ':' {
137
137
key := unsafeBytesToString (data [keyBegin :keyEnd ])
138
138
139
- if keyLevel == level - 1 && // If key nesting level match current object nested level
139
+ if keyLevel == level - 1 && // If key nesting level match current object nested level
140
140
keys [level - 1 ] == key {
141
141
keyLevel ++
142
142
// If we found all keys in path
@@ -462,3 +462,34 @@ func unsafeBytesToString(data []byte) string {
462
462
sh := reflect.StringHeader {Data : h .Data , Len : h .Len }
463
463
return * (* string )(unsafe .Pointer (& sh ))
464
464
}
465
+
466
+ // ParsePrimitiveValue takes a []byte value returned by Get(), passed to ArrayEach() callback, etc.
467
+ // and parses/converts it into a Go type (wrapped in an interface{}) as follows:
468
+ //
469
+ // Null -> nil
470
+ // Boolean -> bool
471
+ // String -> string (unescaped)
472
+ // Number -> float64
473
+ // anything else -> error
474
+ //
475
+ // This function will likely a memory allocation to return an interface{}, but often user code
476
+ // needs an interface{} value, so we provide an efficient implementation for when it is needed.
477
+ //
478
+ func ParsePrimitiveValue (vbytes []byte , jtype ValueType ) (interface {}, error ) {
479
+ switch jtype {
480
+ case Null :
481
+ return nil , nil
482
+ case Boolean :
483
+ return (vbytes [0 ] == 't' ), nil // assumes value is already validated by Get(), etc. since we're given jtype == Boolean
484
+ case String :
485
+ return string (vbytes ), nil // TODO: this does not unescape the string; use unescaper whenever it becomes available
486
+ case Number :
487
+ if v , err := strconv .ParseFloat (unsafeBytesToString (vbytes ), 64 ); err != nil { // TODO: use better BytesParseFloat in PR #25
488
+ return nil , MalformedValueError
489
+ } else {
490
+ return v , nil
491
+ }
492
+ default :
493
+ return nil , NotAPrimitiveError
494
+ }
495
+ }
0 commit comments