|
@@ -3,7 +3,10 @@ package node
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
+ "io"
|
|
|
+ "os"
|
|
|
"reflect"
|
|
|
+ "strings"
|
|
|
)
|
|
|
|
|
|
type Node struct {
|
|
@@ -33,6 +36,85 @@ func NewNodeWithDataAndName(data any, name string) *Node {
|
|
|
return &Node{name: name, data: data}
|
|
|
}
|
|
|
|
|
|
+func NewNodeFromJSON(data []byte) (*Node, error) {
|
|
|
+ n := NewNode()
|
|
|
+ err := json.Unmarshal(data, &n)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ return n, nil
|
|
|
+}
|
|
|
+
|
|
|
+func NewNodeFromFile(name string) (*Node, error) {
|
|
|
+ pay, err := os.ReadFile(name)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ return NewNodeFromJSON(pay)
|
|
|
+}
|
|
|
+
|
|
|
+func NewNodeFromStream(r io.Reader) (*Node, error) {
|
|
|
+ doc := json.NewDecoder(r)
|
|
|
+ root := NewNode()
|
|
|
+ work := root
|
|
|
+ var (
|
|
|
+ depth int = 0
|
|
|
+ maplike bool = false
|
|
|
+ lastToken string
|
|
|
+ )
|
|
|
+ for {
|
|
|
+ t, err := doc.Token()
|
|
|
+ if err == io.EOF {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ delim, ok := t.(json.Delim)
|
|
|
+ if ok {
|
|
|
+ if rune(delim) == '{' || rune(delim) == '[' {
|
|
|
+ work = work.NewKid()
|
|
|
+ depth++
|
|
|
+ if rune(delim) == '{' {
|
|
|
+ maplike = true
|
|
|
+ } else {
|
|
|
+ maplike = false
|
|
|
+ }
|
|
|
+ } else if rune(delim) == '}' || rune(delim) == ']' {
|
|
|
+ if work.Parent() != nil {
|
|
|
+ depth--
|
|
|
+ work = work.Parent()
|
|
|
+ maplike = work.IsMapLike()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ text := fmt.Sprintf("%v", t)
|
|
|
+ if lastToken == "" {
|
|
|
+ lastToken = text
|
|
|
+ } else {
|
|
|
+ lastToken = ""
|
|
|
+ }
|
|
|
+ fmt.Printf("%s%s", strings.Repeat(" ", depth), text)
|
|
|
+ if doc.More() {
|
|
|
+ fmt.Printf(" (more)")
|
|
|
+ }
|
|
|
+ fmt.Printf("\n")
|
|
|
+ if work.Name() == "" && maplike {
|
|
|
+ work.Name(text)
|
|
|
+ } else if maplike {
|
|
|
+ if !doc.More() {
|
|
|
+ work.Data(t.(any))
|
|
|
+ } else {
|
|
|
+ work.NewKidWithData(t.(any))
|
|
|
+ }
|
|
|
+ } else if !maplike {
|
|
|
+ work.NewKidWithData(t.(any))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return root, nil
|
|
|
+}
|
|
|
+
|
|
|
func (n *Node) Name(name ...string) string {
|
|
|
if len(name) != 0 {
|
|
|
n.name = name[0]
|