-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobject.go
95 lines (77 loc) · 1.82 KB
/
object.go
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
package orderedobject
import (
"encoding/json"
"strings"
)
// Pair represents a key value pair.
type Pair[V any] struct {
// Key is the pair's key.
Key string
// Value is the pair's value.
Value V
}
// Object represents a JSON object that respects insertion order.
type Object[V any] []*Pair[V]
// Set sets key in object with the given value.
//
// The key is replaced if it already exists.
func (object *Object[V]) Set(key string, value V) {
for _, pair := range *object {
if pair.Key == key {
pair.Value = value
return
}
}
*object = append(*object, &Pair[V]{key, value})
}
// Has reports if the given key is set.
func (object *Object[V]) Has(key string) bool {
for _, pair := range *object {
if pair.Key == key {
return true
}
}
return false
}
// Get gets the value of key.
//
// The returned value is V's zero value if key isn't set.
func (object *Object[V]) Get(key string) V {
for _, pair := range *object {
if pair.Key == key {
return pair.Value
}
}
// "hack" to get V's zero value
var empty V
return empty
}
// MarshalJSON encodes the object into JSON format, respecting insertion order in the process.
func (object *Object[V]) MarshalJSON() ([]byte, error) {
var builder strings.Builder
// Start of object
builder.WriteString("{")
for _, pair := range *object {
// Write comma if this isn't the first entry
if builder.Len() > 1 {
builder.WriteString(",")
}
// Write key
encodedKey, err := json.Marshal(pair.Key)
if err != nil {
return nil, err
}
builder.WriteString(string(encodedKey))
// Write separator
builder.WriteString(":")
// Write value
encodedValue, err := json.Marshal(pair.Value)
if err != nil {
return nil, err
}
builder.WriteString(string(encodedValue))
}
// End of object
builder.WriteString("}")
return []byte(builder.String()), nil
}