types/opt: make jsonv2 dependency optional behind ts_omit_jsonv2 tag

Updates #TODO

Signed-off-by: Paul Scott <paul@tailscale.com>
This commit is contained in:
Paul Scott 2025-02-26 11:07:30 +00:00
parent 820bdb870a
commit 36d4b831af
3 changed files with 74 additions and 32 deletions

View File

@ -6,9 +6,6 @@ package opt
import (
"fmt"
"reflect"
jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext"
)
// Value is an optional value to be JSON-encoded.
@ -99,32 +96,3 @@ func (o Value[T]) Equal(v Value[T]) bool {
}
return false
}
// MarshalJSONV2 implements [jsonv2.MarshalerV2].
func (o Value[T]) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
if !o.set {
return enc.WriteToken(jsontext.Null)
}
return jsonv2.MarshalEncode(enc, &o.value, opts)
}
// UnmarshalJSONV2 implements [jsonv2.UnmarshalerV2].
func (o *Value[T]) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
if dec.PeekKind() == 'n' {
*o = Value[T]{}
_, err := dec.ReadToken() // read null
return err
}
o.set = true
return jsonv2.UnmarshalDecode(dec, &o.value, opts)
}
// MarshalJSON implements [json.Marshaler].
func (o Value[T]) MarshalJSON() ([]byte, error) {
return jsonv2.Marshal(o) // uses MarshalJSONV2
}
// UnmarshalJSON implements [json.Unmarshaler].
func (o *Value[T]) UnmarshalJSON(b []byte) error {
return jsonv2.Unmarshal(b, o) // uses UnmarshalJSONV2
}

34
types/opt/value_jsonv1.go Normal file
View File

@ -0,0 +1,34 @@
//go:build ts_omit_jsonv2
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package value
import (
"bytes"
"encoding/json"
"fmt"
)
var null = []byte("null")
// MarshalJSON implements [json.Marshaler].
func (o Value[T]) MarshalJSON() ([]byte, error) {
if !o.set {
return null, nil
}
return json.Marshal(o.value)
}
// UnmarshalJSON implements [json.Unmarshaler].
func (o *Value[T]) UnmarshalJSON(b []byte) error {
if len(b) > 0 && b[0] == 'n' {
*o = Value[T]{}
if !bytes.Equal(b, null) {
return fmt.Errorf("invalid literal %q, expected %q", b, null)
}
return nil
}
return json.Unmarshal(&o.value, b)
}

40
types/opt/value_jsonv2.go Normal file
View File

@ -0,0 +1,40 @@
//go:build !ts_omit_jsonv2
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package opt
import (
jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext"
)
// MarshalJSON implements [json.Marshaler].
func (o Value[T]) MarshalJSON() ([]byte, error) {
return jsonv2.Marshal(o) // uses MarshalJSONV2
}
// UnmarshalJSON implements [json.Unmarshaler].
func (o *Value[T]) UnmarshalJSON(b []byte) error {
return jsonv2.Unmarshal(b, o) // uses UnmarshalJSONV2
}
// MarshalJSONV2 implements [jsonv2.MarshalerV2].
func (o Value[T]) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
if !o.set {
return enc.WriteToken(jsontext.Null)
}
return jsonv2.MarshalEncode(enc, &o.value, opts)
}
// UnmarshalJSONV2 implements [jsonv2.UnmarshalerV2].
func (o *Value[T]) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
if dec.PeekKind() == 'n' {
*o = Value[T]{}
_, err := dec.ReadToken() // read null
return err
}
o.set = true
return jsonv2.UnmarshalDecode(dec, &o.value, opts)
}