@@ -11,95 +11,71 @@ import (
1111 "io"
1212)
1313
14- // isJSONv2Available returns true when JSON v2 is available (compiled with GOEXPERIMENT=jsonv2)
15- func isJSONv2Available () bool {
16- return true
14+ // JSONv2 implements Interface via encoding/json/v2
15+ // Requires GOEXPERIMENT=jsonv2 to be set at build time
16+ type JSONv2 struct {}
17+
18+ var _ Interface = JSONv2 {}
19+
20+ func getDefaultJSONHandler () Interface {
21+ return JSONv2 {}
1722}
1823
19- // marshalV2Internal uses JSON v2 marshal with v1 compatibility options (no trailing newline)
20- func marshalV2Internal (v any ) ([]byte , error ) {
21- opts := jsonv2 .JoinOptions (
24+ func jsonv2DefaultMarshalOptions () jsonv2.Options {
25+ return jsonv2 .JoinOptions (
2226 jsonv2 .MatchCaseInsensitiveNames (true ),
2327 jsonv2 .FormatNilSliceAsNull (true ),
2428 jsonv2 .FormatNilMapAsNull (true ),
2529 jsonv2 .Deterministic (true ),
2630 )
27- return jsonv2 .Marshal (v , opts )
2831}
2932
30- // marshalV2 uses JSON v2 marshal with v1 compatibility options (with trailing newline for compatibility with standard library)
31- func marshalV2 (v any ) ([]byte , error ) {
32- result , err := marshalV2Internal (v )
33- if err != nil {
34- return nil , err
35- }
36-
37- return append (result , '\n' ), nil
33+ func jsonv2DefaultUnmarshalOptions () jsonv2.Options {
34+ return jsonv2 .JoinOptions (
35+ jsonv2 .MatchCaseInsensitiveNames (true ),
36+ )
3837}
3938
40- // unmarshalV2 uses JSON v2 unmarshal with v1 compatibility options
41- func unmarshalV2 (data []byte , v any ) error {
42- if len (data ) == 0 {
43- return nil
44- }
39+ func (JSONv2 ) Marshal (v any ) ([]byte , error ) {
40+ return jsonv2 .Marshal (v , jsonv2DefaultMarshalOptions ())
41+ }
4542
43+ func (JSONv2 ) Unmarshal (data []byte , v any ) error {
44+ // legacy behavior: treat empty or whitespace-only input as no input, it should be safe
4645 data = bytes .TrimSpace (data )
4746 if len (data ) == 0 {
4847 return nil
4948 }
49+ return jsonv2 .Unmarshal (data , v , jsonv2DefaultUnmarshalOptions ())
50+ }
5051
51- opts := jsonv2 .JoinOptions (
52- jsonv2 .MatchCaseInsensitiveNames (true ),
53- )
54- return jsonv2 .Unmarshal (data , v , opts )
52+ func (JSONv2 ) NewEncoder (writer io.Writer ) Encoder {
53+ return & encoderV2 {writer : writer , opts : jsonv2DefaultMarshalOptions ()}
54+ }
55+
56+ func (JSONv2 ) NewDecoder (reader io.Reader ) Decoder {
57+ return & decoderV2 {reader : reader , opts : jsonv2DefaultMarshalOptions ()}
58+ }
59+
60+ // Indent implements Interface using standard library (JSON v2 doesn't have Indent yet)
61+ func (JSONv2 ) Indent (dst * bytes.Buffer , src []byte , prefix , indent string ) error {
62+ return json .Indent (dst , src , prefix , indent )
5563}
5664
57- // encoderV2 wraps JSON v2 streaming encoder
5865type encoderV2 struct {
5966 writer io.Writer
6067 opts jsonv2.Options
6168}
6269
6370func (e * encoderV2 ) Encode (v any ) error {
64- err := jsonv2 .MarshalWrite (e .writer , v , e .opts )
65- if err != nil {
66- return err
67- }
68-
69- _ , err = e .writer .Write ([]byte {'\n' })
70- return err
71+ return jsonv2 .MarshalWrite (e .writer , v , e .opts )
7172}
7273
73- // newEncoderV2 creates a new JSON v2 streaming encoder
74- func newEncoderV2 (writer io.Writer ) Encoder {
75- opts := jsonv2 .JoinOptions (
76- jsonv2 .MatchCaseInsensitiveNames (true ),
77- jsonv2 .FormatNilSliceAsNull (true ),
78- jsonv2 .FormatNilMapAsNull (true ),
79- jsonv2 .Deterministic (true ),
80- )
81- return & encoderV2 {writer : writer , opts : opts }
82- }
83-
84- // decoderV2 wraps JSON v2 streaming decoder
8574type decoderV2 struct {
8675 reader io.Reader
8776 opts jsonv2.Options
8877}
8978
9079func (d * decoderV2 ) Decode (v any ) error {
91- err := jsonv2 .UnmarshalRead (d .reader , v , d .opts )
92- // Handle EOF more gracefully to match standard library behavior
93- if err != nil && err .Error () == "unexpected EOF" {
94- return io .EOF
95- }
96- return err
97- }
98-
99- // newDecoderV2 creates a new JSON v2 streaming decoder
100- func newDecoderV2 (reader io.Reader ) Decoder {
101- opts := jsonv2 .JoinOptions (
102- jsonv2 .MatchCaseInsensitiveNames (true ),
103- )
104- return & decoderV2 {reader : reader , opts : opts }
80+ return jsonv2 .UnmarshalRead (d .reader , v , d .opts )
10581}
0 commit comments