From a321bfe7b2f6db5078de7b2e5ed5ddcccd65f319 Mon Sep 17 00:00:00 2001 From: NeonXP Date: Wed, 16 Nov 2022 05:11:19 +0300 Subject: initial commit --- model/node.go | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 model/node.go (limited to 'model/node.go') diff --git a/model/node.go b/model/node.go new file mode 100644 index 0000000..1483eaf --- /dev/null +++ b/model/node.go @@ -0,0 +1,115 @@ +package model + +import ( + "bytes" + "fmt" + "strconv" +) + +// Node of JSON tree +type Node struct { + Type NodeType + stringValue string + numberValue float64 + objectValue NodeObjectValue + arrayValue NodeArrayValue + booleanValue bool +} + +// NewNode creates new node from value +func NewNode(value any) *Node { + n := new(Node) + n.SetValue(value) + return n +} + +// Value returns value of node +func (n *Node) Value() any { + switch n.Type { + case StringNode: + return n.stringValue + case NumberNode: + return n.numberValue + case ObjectNode: + return n.objectValue + case ArrayNode: + return n.arrayValue + case BooleanNode: + return n.booleanValue + default: + return nil + } +} + +// SetValue to node +func (n *Node) SetValue(value any) { + switch value := value.(type) { + case string: + n.Type = StringNode + n.stringValue = value + case float64: + n.Type = NumberNode + n.numberValue = value + case int: + n.Type = NumberNode + n.numberValue = float64(value) + case NodeObjectValue: + n.Type = ObjectNode + n.objectValue = value + case NodeArrayValue: + n.Type = ArrayNode + n.arrayValue = value + case bool: + n.Type = BooleanNode + n.booleanValue = value + default: + n.Type = NullNode + } +} + +// MarshalJSON to []byte +func (n *Node) MarshalJSON() ([]byte, error) { + switch n.Type { + case StringNode: + return []byte(`"` + n.stringValue + `"`), nil + case NumberNode: + return []byte(strconv.FormatFloat(n.numberValue, 'g', -1, 64)), nil + case ObjectNode: + result := make([][]byte, 0, len(n.objectValue)) + for k, v := range n.objectValue { + b, err := v.MarshalJSON() + if err != nil { + return nil, err + } + result = append(result, []byte(fmt.Sprintf("\"%s\": %s", k, b))) + } + return bytes.Join( + [][]byte{ + []byte("{"), + bytes.Join(result, []byte(", ")), + []byte("}"), + }, []byte("")), nil + case ArrayNode: + result := make([][]byte, 0, len(n.arrayValue)) + for _, v := range n.arrayValue { + b, err := v.MarshalJSON() + if err != nil { + return nil, err + } + result = append(result, b) + } + return bytes.Join( + [][]byte{ + []byte("["), + bytes.Join(result, []byte(", ")), + []byte("]"), + }, []byte("")), nil + case BooleanNode: + if n.booleanValue { + return []byte("true"), nil + } + return []byte("false"), nil + default: + return []byte("null"), nil + } +} -- cgit v1.2.3