Browse Source

+NewNodeFromJSON,NewNodeFromFile,NewNodeFromStream

NewNodeFromStream is WIP.
Steve Thielemann 1 year ago
parent
commit
46f45e8f67
1 changed files with 82 additions and 0 deletions
  1. 82 0
      node.go

+ 82 - 0
node.go

@@ -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]