diff --git a/cmd/derper/depaware.txt b/cmd/derper/depaware.txt index 1812a1a8d..a61d36a22 100644 --- a/cmd/derper/depaware.txt +++ b/cmd/derper/depaware.txt @@ -14,7 +14,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa L github.com/coreos/go-iptables/iptables from tailscale.com/util/linuxfw W 💣 github.com/dblohm7/wingoes from tailscale.com/util/winutil github.com/fxamacker/cbor/v2 from tailscale.com/tka - github.com/go-json-experiment/json from tailscale.com/types/opt+ + github.com/go-json-experiment/json from tailscale.com/types/views+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json+ github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json+ github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json+ diff --git a/cmd/k8s-operator/depaware.txt b/cmd/k8s-operator/depaware.txt index 54d9bd248..fde34376e 100644 --- a/cmd/k8s-operator/depaware.txt +++ b/cmd/k8s-operator/depaware.txt @@ -100,7 +100,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/ github.com/gaissmai/bart from tailscale.com/net/ipset+ github.com/gaissmai/bart/internal/bitset from github.com/gaissmai/bart+ github.com/gaissmai/bart/internal/sparse from github.com/gaissmai/bart - github.com/go-json-experiment/json from tailscale.com/types/opt+ + github.com/go-json-experiment/json from tailscale.com/types/views+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json/internal/jsonflags+ github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json/internal/jsonopts+ github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json/jsontext+ diff --git a/cmd/stund/depaware.txt b/cmd/stund/depaware.txt index 1d0a093c4..8c75f2f4e 100644 --- a/cmd/stund/depaware.txt +++ b/cmd/stund/depaware.txt @@ -2,7 +2,7 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar github.com/beorn7/perks/quantile from github.com/prometheus/client_golang/prometheus 💣 github.com/cespare/xxhash/v2 from github.com/prometheus/client_golang/prometheus - github.com/go-json-experiment/json from tailscale.com/types/opt + github.com/go-json-experiment/json from tailscale.com/types/views+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json+ github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json+ github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json+ diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index afe62165c..0f1021114 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -9,7 +9,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep W 💣 github.com/dblohm7/wingoes from github.com/dblohm7/wingoes/pe+ W 💣 github.com/dblohm7/wingoes/pe from tailscale.com/util/winutil/authenticode github.com/fxamacker/cbor/v2 from tailscale.com/tka - github.com/go-json-experiment/json from tailscale.com/types/opt+ + github.com/go-json-experiment/json from tailscale.com/types/views+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json+ github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json+ github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json+ diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index c0f592ea1..91e8875ff 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -94,7 +94,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de github.com/gaissmai/bart from tailscale.com/net/tstun+ github.com/gaissmai/bart/internal/bitset from github.com/gaissmai/bart+ github.com/gaissmai/bart/internal/sparse from github.com/gaissmai/bart - github.com/go-json-experiment/json from tailscale.com/types/opt+ + github.com/go-json-experiment/json from tailscale.com/types/views+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json/internal/jsonflags+ github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json/internal/jsonopts+ github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json/jsontext+ diff --git a/types/views/views_jsonv2.go b/types/views/views_jsonv2.go new file mode 100644 index 000000000..025c58b63 --- /dev/null +++ b/types/views/views_jsonv2.go @@ -0,0 +1,41 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !ts_omit_jsonv2 + +package views + +import ( + jsonv2 "github.com/go-json-experiment/json" + "github.com/go-json-experiment/json/jsontext" +) + +// MarshalJSONV2 implements jsonv2.MarshalerV2. +func (m MapSlice[K, v]) MarshalJSONV2(e *jsontext.Encoder, opt jsonv2.Options) error { + return jsonv2.MarshalEncode(e, m.ж, opt) +} + +// MarshalJSONV2 implements jsonv2.MarshalerV2. +func (m Map[K, V]) MarshalJSONV2(e *jsontext.Encoder, opt jsonv2.Options) error { + return jsonv2.MarshalEncode(e, m.ж, opt) +} + +// MarshalJSONV2 implements jsonv2.MarshalerV2. +func (v ByteSlice[T]) MarshalJSONV2(e *jsontext.Encoder, opt jsonv2.Options) error { + return jsonv2.MarshalEncode(e, v.ж, opt) +} + +// MarshalJSONV2 implements jsonv2.MarshalerV2. +func (v SliceView[T, V]) MarshalJSONV2(e *jsontext.Encoder, opt jsonv2.Options) error { + return jsonv2.MarshalEncode(e, v.ж, opt) +} + +// MarshalJSONV2 implements jsonv2.MarshalerV2. +func (v Slice[T]) MarshalJSONV2(e *jsontext.Encoder, opt jsonv2.Options) error { + return jsonv2.MarshalEncode(e, v.ж, opt) +} + +// MarshalJSONV2 implements jsonv2.MarshalerV2. +func (p ValuePointer[T]) MarshalJSONV2(e *jsontext.Encoder, opt jsonv2.Options) error { + return jsonv2.MarshalEncode(e, p.ж, opt) +} diff --git a/types/views/views_jsonv2_test.go b/types/views/views_jsonv2_test.go new file mode 100644 index 000000000..878557986 --- /dev/null +++ b/types/views/views_jsonv2_test.go @@ -0,0 +1,85 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !ts_omit_jsonv2 + +package views + +import ( + "encoding/json" + "testing" + + jsonv2 "github.com/go-json-experiment/json" + "github.com/google/go-cmp/cmp" +) + +func TestByteSlice_MarshalJSONV2(t *testing.T) { + compareJSONv1v2(t, ByteSliceOf([]byte{})) + compareJSONv1v2(t, ByteSliceOf(alwaysMarshalSliceV1[byte]([]byte{255}))) +} + +func TestSliceView_MarshalJSONV2(t *testing.T) { + compareJSONv1v2(t, SliceOfViews([]*testobj{ + {1}, + {"a"}, + {alwaysMarshalSliceV1[bool]([]bool{true, false})}, + })) +} + +func TestSlice_MarshalJSONV2(t *testing.T) { + compareJSONv1v2(t, SliceOf([]int{1, 2, 3})) + compareJSONv1v2(t, SliceOf(alwaysMarshalSliceV1[int]([]int{4, 5, 6}))) +} + +func TestMapSlice_MarshalJSONV2(t *testing.T) { + compareJSONv1v2(t, MapSliceOf(map[string][]int{"a": {1, 2, 3}})) + compareJSONv1v2(t, MapSliceOf(map[string][]alwaysMarshalSliceV1[int]{"a": {{1, 2, 3}}})) +} + +func TestMap_MarshalJSONV2(t *testing.T) { + compareJSONv1v2(t, MapOf(map[string]int{"a": 1, "b": 2})) + compareJSONv1v2(t, MapOf(map[string]alwaysMarshalSliceV1[int]{"a": {1, 2, 3}})) +} + +func TestValuePointer_MarshalJSONV2(t *testing.T) { + compareJSONv1v2(t, ValuePointerOf(&testobj{})) + compareJSONv1v2(t, ValuePointerOf(&alwaysMarshalSliceV1[int]{1, 2, 3})) +} + +type testobj struct{ V any } + +func (o *testobj) Clone() *testobj { return o } +func (o *testobj) View() testobjView { return testobjView{o} } + +type testobjView struct{ O *testobj } + +func (v testobjView) Valid() bool { return v.O != nil } +func (v testobjView) AsStruct() *testobj { return v.O } + +var ( + _ ViewCloner[*testobj, testobjView] = (*testobj)(nil) + _ StructView[*testobj] = testobjView{} +) + +type alwaysMarshalSliceV1[T any] []T + +func (m alwaysMarshalSliceV1[T]) MarshalJSON() ([]byte, error) { + return []byte(`"v1"`), nil +} + +func compareJSONv1v2(t testing.TB, v any) { + t.Helper() + b1, err := json.Marshal(v) + if err != nil { + t.Fatalf("json.Marshal(%T) failed: %s", v, err) + } + b2, err := jsonv2.Marshal(v, jsonv2.Deterministic(true)) + if err != nil { + t.Fatalf("jsonv2.Marshal(%T) failed: %s", v, err) + } + t.Logf("%T:\nv1: %s\nv2: %s", v, b1, b2) + + if d := cmp.Diff(string(b1), string(b2)); d != "" { + t.Fatalf("json %T diff (-v1 +v2)\n%s", v, d) + } +}