1 package decoder
2
3 import (
4 "fmt"
5 "reflect"
6 "strconv"
7
8 "github.com/goccy/go-json/internal/errors"
9 "github.com/goccy/go-json/internal/runtime"
10 )
11
12 type PathString string
13
14 func (s PathString) Build() (*Path, error) {
15 builder := new(PathBuilder)
16 return builder.Build([]rune(s))
17 }
18
19 type PathBuilder struct {
20 root PathNode
21 node PathNode
22 singleQuotePathSelector bool
23 doubleQuotePathSelector bool
24 }
25
26 func (b *PathBuilder) Build(buf []rune) (*Path, error) {
27 node, err := b.build(buf)
28 if err != nil {
29 return nil, err
30 }
31 return &Path{
32 node: node,
33 RootSelectorOnly: node == nil,
34 SingleQuotePathSelector: b.singleQuotePathSelector,
35 DoubleQuotePathSelector: b.doubleQuotePathSelector,
36 }, nil
37 }
38
39 func (b *PathBuilder) build(buf []rune) (PathNode, error) {
40 if len(buf) == 0 {
41 return nil, errors.ErrEmptyPath()
42 }
43 if buf[0] != '$' {
44 return nil, errors.ErrInvalidPath("JSON Path must start with a $ character")
45 }
46 if len(buf) == 1 {
47 return nil, nil
48 }
49 buf = buf[1:]
50 offset, err := b.buildNext(buf)
51 if err != nil {
52 return nil, err
53 }
54 if len(buf) > offset {
55 return nil, errors.ErrInvalidPath("remain invalid path %q", buf[offset:])
56 }
57 return b.root, nil
58 }
59
60 func (b *PathBuilder) buildNextCharIfExists(buf []rune, cursor int) (int, error) {
61 if len(buf) > cursor {
62 offset, err := b.buildNext(buf[cursor:])
63 if err != nil {
64 return 0, err
65 }
66 return cursor + 1 + offset, nil
67 }
68 return cursor, nil
69 }
70
71 func (b *PathBuilder) buildNext(buf []rune) (int, error) {
72 switch buf[0] {
73 case '.':
74 if len(buf) == 1 {
75 return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
76 }
77 offset, err := b.buildSelector(buf[1:])
78 if err != nil {
79 return 0, err
80 }
81 return offset + 1, nil
82 case '[':
83 if len(buf) == 1 {
84 return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
85 }
86 offset, err := b.buildIndex(buf[1:])
87 if err != nil {
88 return 0, err
89 }
90 return offset + 1, nil
91 default:
92 return 0, errors.ErrInvalidPath("expect dot or left bracket character. but found %c character", buf[0])
93 }
94 }
95
96 func (b *PathBuilder) buildSelector(buf []rune) (int, error) {
97 switch buf[0] {
98 case '.':
99 if len(buf) == 1 {
100 return 0, errors.ErrInvalidPath("JSON Path ends with double dot character")
101 }
102 offset, err := b.buildPathRecursive(buf[1:])
103 if err != nil {
104 return 0, err
105 }
106 return 1 + offset, nil
107 case '[', ']', '$', '*':
108 return 0, errors.ErrInvalidPath("found invalid path character %c after dot", buf[0])
109 }
110 for cursor := 0; cursor < len(buf); cursor++ {
111 switch buf[cursor] {
112 case '$', '*', ']':
113 return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor])
114 case '.':
115 if cursor+1 >= len(buf) {
116 return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
117 }
118 selector := buf[:cursor]
119 b.addSelectorNode(string(selector))
120 offset, err := b.buildSelector(buf[cursor+1:])
121 if err != nil {
122 return 0, err
123 }
124 return cursor + 1 + offset, nil
125 case '[':
126 if cursor+1 >= len(buf) {
127 return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
128 }
129 selector := buf[:cursor]
130 b.addSelectorNode(string(selector))
131 offset, err := b.buildIndex(buf[cursor+1:])
132 if err != nil {
133 return 0, err
134 }
135 return cursor + 1 + offset, nil
136 case '"':
137 if cursor+1 >= len(buf) {
138 return 0, errors.ErrInvalidPath("JSON Path ends with double quote character")
139 }
140 offset, err := b.buildQuoteSelector(buf[cursor+1:], DoubleQuotePathSelector)
141 if err != nil {
142 return 0, err
143 }
144 return cursor + 1 + offset, nil
145 }
146 }
147 b.addSelectorNode(string(buf))
148 return len(buf), nil
149 }
150
151 func (b *PathBuilder) buildQuoteSelector(buf []rune, sel QuotePathSelector) (int, error) {
152 switch buf[0] {
153 case '[', ']', '$', '.', '*', '\'', '"':
154 return 0, errors.ErrInvalidPath("found invalid path character %c after quote", buf[0])
155 }
156 for cursor := 0; cursor < len(buf); cursor++ {
157 switch buf[cursor] {
158 case '\'':
159 if sel != SingleQuotePathSelector {
160 return 0, errors.ErrInvalidPath("found double quote character in field selector with single quote context")
161 }
162 if len(buf) <= cursor+1 {
163 return 0, errors.ErrInvalidPath("JSON Path ends with single quote character in field selector context")
164 }
165 if buf[cursor+1] != ']' {
166 return 0, errors.ErrInvalidPath("expect right bracket for field selector with single quote but found %c", buf[cursor+1])
167 }
168 selector := buf[:cursor]
169 b.addSelectorNode(string(selector))
170 b.singleQuotePathSelector = true
171 return b.buildNextCharIfExists(buf, cursor+2)
172 case '"':
173 if sel != DoubleQuotePathSelector {
174 return 0, errors.ErrInvalidPath("found single quote character in field selector with double quote context")
175 }
176 selector := buf[:cursor]
177 b.addSelectorNode(string(selector))
178 b.doubleQuotePathSelector = true
179 return b.buildNextCharIfExists(buf, cursor+1)
180 }
181 }
182 return 0, errors.ErrInvalidPath("couldn't find quote character in selector quote path context")
183 }
184
185 func (b *PathBuilder) buildPathRecursive(buf []rune) (int, error) {
186 switch buf[0] {
187 case '.', '[', ']', '$', '*':
188 return 0, errors.ErrInvalidPath("found invalid path character %c after double dot", buf[0])
189 }
190 for cursor := 0; cursor < len(buf); cursor++ {
191 switch buf[cursor] {
192 case '$', '*', ']':
193 return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor])
194 case '.':
195 if cursor+1 >= len(buf) {
196 return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
197 }
198 selector := buf[:cursor]
199 b.addRecursiveNode(string(selector))
200 offset, err := b.buildSelector(buf[cursor+1:])
201 if err != nil {
202 return 0, err
203 }
204 return cursor + 1 + offset, nil
205 case '[':
206 if cursor+1 >= len(buf) {
207 return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
208 }
209 selector := buf[:cursor]
210 b.addRecursiveNode(string(selector))
211 offset, err := b.buildIndex(buf[cursor+1:])
212 if err != nil {
213 return 0, err
214 }
215 return cursor + 1 + offset, nil
216 }
217 }
218 b.addRecursiveNode(string(buf))
219 return len(buf), nil
220 }
221
222 func (b *PathBuilder) buildIndex(buf []rune) (int, error) {
223 switch buf[0] {
224 case '.', '[', ']', '$':
225 return 0, errors.ErrInvalidPath("found invalid path character %c after left bracket", buf[0])
226 case '\'':
227 if len(buf) == 1 {
228 return 0, errors.ErrInvalidPath("JSON Path ends with single quote character")
229 }
230 offset, err := b.buildQuoteSelector(buf[1:], SingleQuotePathSelector)
231 if err != nil {
232 return 0, err
233 }
234 return 1 + offset, nil
235 case '*':
236 if len(buf) == 1 {
237 return 0, errors.ErrInvalidPath("JSON Path ends with star character")
238 }
239 if buf[1] != ']' {
240 return 0, errors.ErrInvalidPath("expect right bracket character for index all path but found %c character", buf[1])
241 }
242 b.addIndexAllNode()
243 offset := len("*]")
244 if len(buf) > 2 {
245 buildOffset, err := b.buildNext(buf[2:])
246 if err != nil {
247 return 0, err
248 }
249 return offset + buildOffset, nil
250 }
251 return offset, nil
252 }
253
254 for cursor := 0; cursor < len(buf); cursor++ {
255 switch buf[cursor] {
256 case ']':
257 index, err := strconv.ParseInt(string(buf[:cursor]), 10, 64)
258 if err != nil {
259 return 0, errors.ErrInvalidPath("%q is unexpected index path", buf[:cursor])
260 }
261 b.addIndexNode(int(index))
262 return b.buildNextCharIfExists(buf, cursor+1)
263 }
264 }
265 return 0, errors.ErrInvalidPath("couldn't find right bracket character in index path context")
266 }
267
268 func (b *PathBuilder) addIndexAllNode() {
269 node := newPathIndexAllNode()
270 if b.root == nil {
271 b.root = node
272 b.node = node
273 } else {
274 b.node = b.node.chain(node)
275 }
276 }
277
278 func (b *PathBuilder) addRecursiveNode(selector string) {
279 node := newPathRecursiveNode(selector)
280 if b.root == nil {
281 b.root = node
282 b.node = node
283 } else {
284 b.node = b.node.chain(node)
285 }
286 }
287
288 func (b *PathBuilder) addSelectorNode(name string) {
289 node := newPathSelectorNode(name)
290 if b.root == nil {
291 b.root = node
292 b.node = node
293 } else {
294 b.node = b.node.chain(node)
295 }
296 }
297
298 func (b *PathBuilder) addIndexNode(idx int) {
299 node := newPathIndexNode(idx)
300 if b.root == nil {
301 b.root = node
302 b.node = node
303 } else {
304 b.node = b.node.chain(node)
305 }
306 }
307
308 type QuotePathSelector int
309
310 const (
311 SingleQuotePathSelector QuotePathSelector = 1
312 DoubleQuotePathSelector QuotePathSelector = 2
313 )
314
315 type Path struct {
316 node PathNode
317 RootSelectorOnly bool
318 SingleQuotePathSelector bool
319 DoubleQuotePathSelector bool
320 }
321
322 func (p *Path) Field(sel string) (PathNode, bool, error) {
323 if p.node == nil {
324 return nil, false, nil
325 }
326 return p.node.Field(sel)
327 }
328
329 func (p *Path) Get(src, dst reflect.Value) error {
330 if p.node == nil {
331 return nil
332 }
333 return p.node.Get(src, dst)
334 }
335
336 func (p *Path) String() string {
337 if p.node == nil {
338 return "$"
339 }
340 return p.node.String()
341 }
342
343 type PathNode interface {
344 fmt.Stringer
345 Index(idx int) (PathNode, bool, error)
346 Field(fieldName string) (PathNode, bool, error)
347 Get(src, dst reflect.Value) error
348 chain(PathNode) PathNode
349 target() bool
350 single() bool
351 }
352
353 type BasePathNode struct {
354 child PathNode
355 }
356
357 func (n *BasePathNode) chain(node PathNode) PathNode {
358 n.child = node
359 return node
360 }
361
362 func (n *BasePathNode) target() bool {
363 return n.child == nil
364 }
365
366 func (n *BasePathNode) single() bool {
367 return true
368 }
369
370 type PathSelectorNode struct {
371 *BasePathNode
372 selector string
373 }
374
375 func newPathSelectorNode(selector string) *PathSelectorNode {
376 return &PathSelectorNode{
377 BasePathNode: &BasePathNode{},
378 selector: selector,
379 }
380 }
381
382 func (n *PathSelectorNode) Index(idx int) (PathNode, bool, error) {
383 return nil, false, &errors.PathError{}
384 }
385
386 func (n *PathSelectorNode) Field(fieldName string) (PathNode, bool, error) {
387 if n.selector == fieldName {
388 return n.child, true, nil
389 }
390 return nil, false, nil
391 }
392
393 func (n *PathSelectorNode) Get(src, dst reflect.Value) error {
394 switch src.Type().Kind() {
395 case reflect.Map:
396 iter := src.MapRange()
397 for iter.Next() {
398 key, ok := iter.Key().Interface().(string)
399 if !ok {
400 return fmt.Errorf("invalid map key type %T", src.Type().Key())
401 }
402 child, found, err := n.Field(key)
403 if err != nil {
404 return err
405 }
406 if found {
407 if child != nil {
408 return child.Get(iter.Value(), dst)
409 }
410 return AssignValue(iter.Value(), dst)
411 }
412 }
413 case reflect.Struct:
414 typ := src.Type()
415 for i := 0; i < typ.Len(); i++ {
416 tag := runtime.StructTagFromField(typ.Field(i))
417 child, found, err := n.Field(tag.Key)
418 if err != nil {
419 return err
420 }
421 if found {
422 if child != nil {
423 return child.Get(src.Field(i), dst)
424 }
425 return AssignValue(src.Field(i), dst)
426 }
427 }
428 case reflect.Ptr:
429 return n.Get(src.Elem(), dst)
430 case reflect.Interface:
431 return n.Get(reflect.ValueOf(src.Interface()), dst)
432 case reflect.Float64, reflect.String, reflect.Bool:
433 return AssignValue(src, dst)
434 }
435 return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type())
436 }
437
438 func (n *PathSelectorNode) String() string {
439 s := fmt.Sprintf(".%s", n.selector)
440 if n.child != nil {
441 s += n.child.String()
442 }
443 return s
444 }
445
446 type PathIndexNode struct {
447 *BasePathNode
448 selector int
449 }
450
451 func newPathIndexNode(selector int) *PathIndexNode {
452 return &PathIndexNode{
453 BasePathNode: &BasePathNode{},
454 selector: selector,
455 }
456 }
457
458 func (n *PathIndexNode) Index(idx int) (PathNode, bool, error) {
459 if n.selector == idx {
460 return n.child, true, nil
461 }
462 return nil, false, nil
463 }
464
465 func (n *PathIndexNode) Field(fieldName string) (PathNode, bool, error) {
466 return nil, false, &errors.PathError{}
467 }
468
469 func (n *PathIndexNode) Get(src, dst reflect.Value) error {
470 switch src.Type().Kind() {
471 case reflect.Array, reflect.Slice:
472 if src.Len() > n.selector {
473 if n.child != nil {
474 return n.child.Get(src.Index(n.selector), dst)
475 }
476 return AssignValue(src.Index(n.selector), dst)
477 }
478 case reflect.Ptr:
479 return n.Get(src.Elem(), dst)
480 case reflect.Interface:
481 return n.Get(reflect.ValueOf(src.Interface()), dst)
482 }
483 return fmt.Errorf("failed to get [%d] value from %s", n.selector, src.Type())
484 }
485
486 func (n *PathIndexNode) String() string {
487 s := fmt.Sprintf("[%d]", n.selector)
488 if n.child != nil {
489 s += n.child.String()
490 }
491 return s
492 }
493
494 type PathIndexAllNode struct {
495 *BasePathNode
496 }
497
498 func newPathIndexAllNode() *PathIndexAllNode {
499 return &PathIndexAllNode{
500 BasePathNode: &BasePathNode{},
501 }
502 }
503
504 func (n *PathIndexAllNode) Index(idx int) (PathNode, bool, error) {
505 return n.child, true, nil
506 }
507
508 func (n *PathIndexAllNode) Field(fieldName string) (PathNode, bool, error) {
509 return nil, false, &errors.PathError{}
510 }
511
512 func (n *PathIndexAllNode) Get(src, dst reflect.Value) error {
513 switch src.Type().Kind() {
514 case reflect.Array, reflect.Slice:
515 var arr []interface{}
516 for i := 0; i < src.Len(); i++ {
517 var v interface{}
518 rv := reflect.ValueOf(&v)
519 if n.child != nil {
520 if err := n.child.Get(src.Index(i), rv); err != nil {
521 return err
522 }
523 } else {
524 if err := AssignValue(src.Index(i), rv); err != nil {
525 return err
526 }
527 }
528 arr = append(arr, v)
529 }
530 if err := AssignValue(reflect.ValueOf(arr), dst); err != nil {
531 return err
532 }
533 return nil
534 case reflect.Ptr:
535 return n.Get(src.Elem(), dst)
536 case reflect.Interface:
537 return n.Get(reflect.ValueOf(src.Interface()), dst)
538 }
539 return fmt.Errorf("failed to get all value from %s", src.Type())
540 }
541
542 func (n *PathIndexAllNode) String() string {
543 s := "[*]"
544 if n.child != nil {
545 s += n.child.String()
546 }
547 return s
548 }
549
550 type PathRecursiveNode struct {
551 *BasePathNode
552 selector string
553 }
554
555 func newPathRecursiveNode(selector string) *PathRecursiveNode {
556 node := newPathSelectorNode(selector)
557 return &PathRecursiveNode{
558 BasePathNode: &BasePathNode{
559 child: node,
560 },
561 selector: selector,
562 }
563 }
564
565 func (n *PathRecursiveNode) Field(fieldName string) (PathNode, bool, error) {
566 if n.selector == fieldName {
567 return n.child, true, nil
568 }
569 return nil, false, nil
570 }
571
572 func (n *PathRecursiveNode) Index(_ int) (PathNode, bool, error) {
573 return n, true, nil
574 }
575
576 func valueToSliceValue(v interface{}) []interface{} {
577 rv := reflect.ValueOf(v)
578 ret := []interface{}{}
579 if rv.Type().Kind() == reflect.Slice || rv.Type().Kind() == reflect.Array {
580 for i := 0; i < rv.Len(); i++ {
581 ret = append(ret, rv.Index(i).Interface())
582 }
583 return ret
584 }
585 return []interface{}{v}
586 }
587
588 func (n *PathRecursiveNode) Get(src, dst reflect.Value) error {
589 if n.child == nil {
590 return fmt.Errorf("failed to get by recursive path ..%s", n.selector)
591 }
592 var arr []interface{}
593 switch src.Type().Kind() {
594 case reflect.Map:
595 iter := src.MapRange()
596 for iter.Next() {
597 key, ok := iter.Key().Interface().(string)
598 if !ok {
599 return fmt.Errorf("invalid map key type %T", src.Type().Key())
600 }
601 child, found, err := n.Field(key)
602 if err != nil {
603 return err
604 }
605 if found {
606 var v interface{}
607 rv := reflect.ValueOf(&v)
608 _ = child.Get(iter.Value(), rv)
609 arr = append(arr, valueToSliceValue(v)...)
610 } else {
611 var v interface{}
612 rv := reflect.ValueOf(&v)
613 _ = n.Get(iter.Value(), rv)
614 if v != nil {
615 arr = append(arr, valueToSliceValue(v)...)
616 }
617 }
618 }
619 _ = AssignValue(reflect.ValueOf(arr), dst)
620 return nil
621 case reflect.Struct:
622 typ := src.Type()
623 for i := 0; i < typ.Len(); i++ {
624 tag := runtime.StructTagFromField(typ.Field(i))
625 child, found, err := n.Field(tag.Key)
626 if err != nil {
627 return err
628 }
629 if found {
630 var v interface{}
631 rv := reflect.ValueOf(&v)
632 _ = child.Get(src.Field(i), rv)
633 arr = append(arr, valueToSliceValue(v)...)
634 } else {
635 var v interface{}
636 rv := reflect.ValueOf(&v)
637 _ = n.Get(src.Field(i), rv)
638 if v != nil {
639 arr = append(arr, valueToSliceValue(v)...)
640 }
641 }
642 }
643 _ = AssignValue(reflect.ValueOf(arr), dst)
644 return nil
645 case reflect.Array, reflect.Slice:
646 for i := 0; i < src.Len(); i++ {
647 var v interface{}
648 rv := reflect.ValueOf(&v)
649 _ = n.Get(src.Index(i), rv)
650 if v != nil {
651 arr = append(arr, valueToSliceValue(v)...)
652 }
653 }
654 _ = AssignValue(reflect.ValueOf(arr), dst)
655 return nil
656 case reflect.Ptr:
657 return n.Get(src.Elem(), dst)
658 case reflect.Interface:
659 return n.Get(reflect.ValueOf(src.Interface()), dst)
660 }
661 return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type())
662 }
663
664 func (n *PathRecursiveNode) String() string {
665 s := fmt.Sprintf("..%s", n.selector)
666 if n.child != nil {
667 s += n.child.String()
668 }
669 return s
670 }
671
View as plain text