Skip to content

Commit bdce391

Browse files
committed
migrate github.com/json-iterator/go to encoding/json/v2
1 parent 379e2f9 commit bdce391

File tree

8 files changed

+248
-283
lines changed

8 files changed

+248
-283
lines changed

fieldpath/path.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (fp Path) Copy() Path {
8080

8181
// MakePath constructs a Path. The parts may be PathElements, ints, strings.
8282
func MakePath(parts ...interface{}) (Path, error) {
83-
var fp Path
83+
fp := make(Path, 0, len(parts))
8484
for _, p := range parts {
8585
switch t := p.(type) {
8686
case PathElement:

fieldpath/serialize-pe.go

Lines changed: 100 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -17,72 +17,101 @@ limitations under the License.
1717
package fieldpath
1818

1919
import (
20+
"bytes"
2021
"errors"
2122
"fmt"
2223
"io"
2324
"strconv"
2425
"strings"
2526

26-
jsoniter "github.com/json-iterator/go"
27+
"github.com/go-json-experiment/json"
28+
"github.com/go-json-experiment/json/jsontext"
2729
"sigs.k8s.io/structured-merge-diff/v6/value"
2830
)
2931

3032
var ErrUnknownPathElementType = errors.New("unknown path element type")
3133

3234
const (
3335
// Field indicates that the content of this path element is a field's name
34-
peField = "f"
36+
peField byte = 'f'
3537

3638
// Value indicates that the content of this path element is a field's value
37-
peValue = "v"
39+
peValue byte = 'v'
3840

3941
// Index indicates that the content of this path element is an index in an array
40-
peIndex = "i"
42+
peIndex byte = 'i'
4143

4244
// Key indicates that the content of this path element is a key value map
43-
peKey = "k"
45+
peKey byte = 'k'
4446

4547
// Separator separates the type of a path element from the contents
46-
peSeparator = ":"
48+
peSeparator byte = ':'
4749
)
4850

4951
var (
50-
peFieldSepBytes = []byte(peField + peSeparator)
51-
peValueSepBytes = []byte(peValue + peSeparator)
52-
peIndexSepBytes = []byte(peIndex + peSeparator)
53-
peKeySepBytes = []byte(peKey + peSeparator)
54-
peSepBytes = []byte(peSeparator)
52+
peFieldSepBytes = []byte{peField, peSeparator}
53+
peValueSepBytes = []byte{peValue, peSeparator}
54+
peIndexSepBytes = []byte{peIndex, peSeparator}
55+
peKeySepBytes = []byte{peKey, peSeparator}
5556
)
5657

57-
// readJSONIter reads a Value from a JSON iterator.
58-
// DO NOT EXPORT
59-
// TODO: eliminate this https://github.com/kubernetes-sigs/structured-merge-diff/issues/202
60-
func readJSONIter(iter *jsoniter.Iterator) (value.Value, error) {
61-
v := iter.Read()
62-
if iter.Error != nil && iter.Error != io.EOF {
63-
return nil, iter.Error
64-
}
65-
return value.NewValueInterface(v), nil
58+
// writeValueToEncoder writes a value to an Encoder.
59+
func writeValueToEncoder(v value.Value, enc *jsontext.Encoder) error {
60+
return json.MarshalEncode(enc, v.Unstructured(), json.Deterministic(true))
6661
}
6762

68-
// writeJSONStream writes a value into a JSON stream.
69-
// DO NOT EXPORT
70-
// TODO: eliminate this https://github.com/kubernetes-sigs/structured-merge-diff/issues/202
71-
func writeJSONStream(v value.Value, stream *jsoniter.Stream) {
72-
stream.WriteVal(v.Unstructured())
63+
// FieldListFromJSON is a helper function for reading a JSON document.
64+
func fieldListFromJSON(input []byte) (value.FieldList, error) {
65+
parser := jsontext.NewDecoder(bytes.NewBuffer(input))
66+
67+
if objStart, err := parser.ReadToken(); err != nil {
68+
return nil, fmt.Errorf("parsing JSON: %v", err)
69+
} else if objStart.Kind() != jsontext.BeginObject.Kind() {
70+
return nil, fmt.Errorf("expected object")
71+
}
72+
73+
var fields value.FieldList
74+
for {
75+
if parser.PeekKind() == jsontext.EndObject.Kind() {
76+
if _, err := parser.ReadToken(); err != nil {
77+
return nil, fmt.Errorf("parsing JSON: %v", err)
78+
}
79+
break
80+
}
81+
82+
rawKey, err := parser.ReadToken()
83+
if err == io.EOF {
84+
return nil, fmt.Errorf("unexpected EOF")
85+
} else if err != nil {
86+
return nil, fmt.Errorf("parsing JSON: %v", err)
87+
}
88+
89+
k := rawKey.String()
90+
91+
var v any
92+
if err := json.UnmarshalDecode(parser, &v); err == io.EOF {
93+
return nil, fmt.Errorf("unexpected EOF")
94+
} else if err != nil {
95+
return nil, fmt.Errorf("parsing JSON: %v", err)
96+
}
97+
98+
fields = append(fields, value.Field{Name: k, Value: value.NewValueInterface(v)})
99+
}
100+
101+
return fields, nil
73102
}
74103

75104
// DeserializePathElement parses a serialized path element
76105
func DeserializePathElement(s string) (PathElement, error) {
77106
b := []byte(s)
78107
if len(b) < 2 {
79-
return PathElement{}, errors.New("key must be 2 characters long:")
108+
return PathElement{}, errors.New("key must be 2 characters long")
80109
}
81-
typeSep, b := b[:2], b[2:]
82-
if typeSep[1] != peSepBytes[0] {
110+
typeSep0, typeSep1, b := b[0], b[1], b[2:]
111+
if typeSep1 != peSeparator {
83112
return PathElement{}, fmt.Errorf("missing colon: %v", s)
84113
}
85-
switch typeSep[0] {
114+
switch typeSep0 {
86115
case peFieldSepBytes[0]:
87116
// Slice s rather than convert b, to save on
88117
// allocations.
@@ -91,29 +120,18 @@ func DeserializePathElement(s string) (PathElement, error) {
91120
FieldName: &str,
92121
}, nil
93122
case peValueSepBytes[0]:
94-
iter := readPool.BorrowIterator(b)
95-
defer readPool.ReturnIterator(iter)
96-
v, err := readJSONIter(iter)
123+
v, err := value.FromJSON(b)
97124
if err != nil {
98125
return PathElement{}, err
99126
}
100127
return PathElement{Value: &v}, nil
101128
case peKeySepBytes[0]:
102-
iter := readPool.BorrowIterator(b)
103-
defer readPool.ReturnIterator(iter)
104-
fields := value.FieldList{}
105-
106-
iter.ReadObjectCB(func(iter *jsoniter.Iterator, key string) bool {
107-
v, err := readJSONIter(iter)
108-
if err != nil {
109-
iter.Error = err
110-
return false
111-
}
112-
fields = append(fields, value.Field{Name: key, Value: v})
113-
return true
114-
})
129+
fields, err := fieldListFromJSON(b)
130+
if err != nil {
131+
return PathElement{}, err
132+
}
115133
fields.Sort()
116-
return PathElement{Key: &fields}, iter.Error
134+
return PathElement{Key: &fields}, nil
117135
case peIndexSepBytes[0]:
118136
i, err := strconv.Atoi(s[2:])
119137
if err != nil {
@@ -127,60 +145,58 @@ func DeserializePathElement(s string) (PathElement, error) {
127145
}
128146
}
129147

130-
var (
131-
readPool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool()
132-
writePool = jsoniter.NewStream(jsoniter.ConfigCompatibleWithStandardLibrary, nil, 1024).Pool()
133-
)
148+
type PathElementSerializer struct {
149+
buffer bytes.Buffer
150+
encoder jsontext.Encoder
151+
}
134152

135153
// SerializePathElement serializes a path element
136154
func SerializePathElement(pe PathElement) (string, error) {
137-
buf := strings.Builder{}
138-
err := serializePathElementToWriter(&buf, pe)
139-
return buf.String(), err
155+
byteVal, err := (&PathElementSerializer{}).serialize(pe)
156+
return string(byteVal), err
140157
}
141158

142-
func serializePathElementToWriter(w io.Writer, pe PathElement) error {
143-
stream := writePool.BorrowStream(w)
144-
defer writePool.ReturnStream(stream)
159+
func (pes *PathElementSerializer) serialize(pe PathElement) (string, error) {
160+
pes.buffer.Reset()
161+
145162
switch {
146163
case pe.FieldName != nil:
147-
if _, err := stream.Write(peFieldSepBytes); err != nil {
148-
return err
164+
if _, err := pes.buffer.Write(peFieldSepBytes); err != nil {
165+
return "", err
149166
}
150-
stream.WriteRaw(*pe.FieldName)
167+
pes.buffer.WriteString(*pe.FieldName)
151168
case pe.Key != nil:
152-
if _, err := stream.Write(peKeySepBytes); err != nil {
153-
return err
169+
if _, err := pes.buffer.Write(peKeySepBytes); err != nil {
170+
return "", err
154171
}
155-
stream.WriteObjectStart()
156-
157-
for i, field := range *pe.Key {
158-
if i > 0 {
159-
stream.WriteMore()
172+
pes.encoder.Reset(&pes.buffer)
173+
pes.encoder.WriteToken(jsontext.BeginObject)
174+
for _, f := range *pe.Key {
175+
if err := pes.encoder.WriteToken(jsontext.String(f.Name)); err != nil {
176+
return "", err
177+
}
178+
if err := writeValueToEncoder(f.Value, &pes.encoder); err != nil {
179+
return "", err
160180
}
161-
stream.WriteObjectField(field.Name)
162-
writeJSONStream(field.Value, stream)
163181
}
164-
stream.WriteObjectEnd()
182+
pes.encoder.WriteToken(jsontext.EndObject)
165183
case pe.Value != nil:
166-
if _, err := stream.Write(peValueSepBytes); err != nil {
167-
return err
184+
if _, err := pes.buffer.Write(peValueSepBytes); err != nil {
185+
return "", err
186+
}
187+
pes.encoder.Reset(&pes.buffer)
188+
if err := writeValueToEncoder(*pe.Value, &pes.encoder); err != nil {
189+
return "", err
168190
}
169-
writeJSONStream(*pe.Value, stream)
170191
case pe.Index != nil:
171-
if _, err := stream.Write(peIndexSepBytes); err != nil {
172-
return err
192+
if _, err := pes.buffer.Write(peIndexSepBytes); err != nil {
193+
return "", err
173194
}
174-
stream.WriteInt(*pe.Index)
195+
pes.buffer.WriteString(strconv.Itoa(*pe.Index))
175196
default:
176-
return errors.New("invalid PathElement")
197+
return "", errors.New("invalid PathElement")
177198
}
178-
b := stream.Buffer()
179-
err := stream.Flush()
180-
// Help jsoniter manage its buffers--without this, the next
181-
// use of the stream is likely to require an allocation. Look
182-
// at the jsoniter stream code to understand why. They were probably
183-
// optimizing for folks using the buffer directly.
184-
stream.SetBuffer(b[:0])
185-
return err
199+
200+
// TODO: is there a way to not emit newlines
201+
return strings.TrimSpace(pes.buffer.String()), nil
186202
}

0 commit comments

Comments
 (0)