1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
package model
import (
"bytes"
"fmt"
"strconv"
)
// Node of JSON tree
type Node struct {
Type NodeType
Meta NodeObjectValue
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
meta, hasMeta := value["@"]
if hasMeta {
n.Meta = meta.ObjectValue
delete(value, "@")
}
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
}
}
// Merge two object or array nodes
func (n *Node) Merge(node *Node) error {
if n.Type != node.Type {
return fmt.Errorf("can't merge nodes of different types")
}
switch n.Type {
case ObjectNode:
for k, v := range node.ObjectValue {
n.ObjectValue[k] = v
}
case ArrayNode:
n.ArrayValue = append(n.ArrayValue, node.ArrayValue...)
default:
return fmt.Errorf("merge not implemented for type %s", n.Type)
}
return nil
}
// Len returns length of object or array nodes
func (n *Node) Len() (int, error) {
switch n.Type {
case ObjectNode:
return len(n.ObjectValue), nil
case ArrayNode:
return len(n.ArrayValue), nil
default:
return 0, fmt.Errorf("merge not implemented for type %s", n.Type)
}
}
// Meta represents node metadata
type Meta map[string]any
|