internal/buildcfg: enable JSONv2 as baseline

This enables the JSONv2 experiment as baseline, meaning that
it is graduating out of the experimental status and
into an production stable status.

By JSONv2 becoming baseline, the v1 "encoding/json" will be
implemented under-the-hood using v2, while preserving v1 semantics.
The older v1-only implementation will be kept around for
a few releases and can be enabled using GOEXPERIMENT=nojsonv2.

Updates #71497

Change-Id: I3fd71f11bf967ac79f72ba35d537aff79bb936e0
Reviewed-on: https://go-review.googlesource.com/c/go/+/773962
Reviewed-by: Austin Clements <austin@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
Joe Tsai 2026-05-04 13:36:53 -07:00 committed by Austin Clements
parent 250d0eb6ee
commit e62d3e6e89
6 changed files with 16 additions and 14 deletions

View file

@ -10,11 +10,6 @@
// primitive data types such as booleans, strings, and numbers,
// in addition to structured data types such as objects and arrays.
//
// This package (encoding/json/jsontext) is experimental,
// and not subject to the Go 1 compatibility promise.
// It only exists when building with the GOEXPERIMENT=jsonv2 environment variable set.
// Most users should use [encoding/json].
//
// The [Encoder] and [Decoder] types are used to encode or decode
// a stream of JSON tokens or values.
//

View file

@ -9,11 +9,6 @@
// primitive data types such as booleans, strings, and numbers,
// in addition to structured data types such as objects and arrays.
//
// This package (encoding/json/v2) is experimental,
// and not subject to the Go 1 compatibility promise.
// It only exists when building with the GOEXPERIMENT=jsonv2 environment variable set.
// Most users should use [encoding/json].
//
// [Marshal] and [Unmarshal] encode and decode Go values
// to/from JSON text contained within a []byte.
// [MarshalWrite] and [UnmarshalRead] operate on JSON text

View file

@ -84,6 +84,7 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) {
Dwarf5: dwarf5Supported,
RandomizedHeapBase64: true,
GreenTeaGC: true,
JSONv2: true,
}
flags := &ExperimentFlags{
Flags: baseline,

View file

@ -10,6 +10,7 @@ import (
"encoding/json"
"errors"
"fmt"
"internal/goexperiment"
"io"
"log/slog/internal/buffer"
"strconv"
@ -220,7 +221,11 @@ func appendEscapedJSONString(buf []byte, s string) []byte {
if start < i {
str(s[start:i])
}
str(`\ufffd`)
if goexperiment.JSONv2 {
str("\ufffd") // see https://go.dev/cl/687116
} else {
str(`\ufffd`)
}
i += size
start = i
continue

View file

@ -10,6 +10,7 @@ import (
"encoding/json"
"errors"
"fmt"
"internal/goexperiment"
"io"
"log/slog/internal/buffer"
"math"
@ -101,6 +102,7 @@ func TestAppendJSONValue(t *testing.T) {
}
if got != want {
t.Errorf("%v: got %s, want %s", value, got, want)
t.Errorf("%v: got %x, want %x", value, got, want)
}
}
}
@ -162,7 +164,11 @@ func TestJSONAllocs(t *testing.T) {
})
})
t.Run("attrs", func(t *testing.T) {
wantAllocs(t, 1, func() {
// TODO(https://go.dev/issue/74617): JSONv2 heap copies aggressively
// to ensure that Go values are addressable in case a pointer method
// must be called. This leads to more allocations than necessary,
// but as an implementation detail, it can eventually be optimized away.
wantAllocs(t, 1+goexperiment.JSONv2Int, func() {
l.LogAttrs(ctx, LevelInfo,
"hello world",
String("component", "subtest"),

View file

@ -862,14 +862,14 @@ func TestUnmarshalInvalidTimes(t *testing.T) {
}{
{`{}`, func() string {
if goexperiment.JSONv2 {
return "json: cannot unmarshal JSON object into Go type time.Time"
return "json: cannot unmarshal object into Go value of type time.Time"
} else {
return "Time.UnmarshalJSON: input is not a JSON string"
}
}()},
{`[]`, func() string {
if goexperiment.JSONv2 {
return "json: cannot unmarshal JSON array into Go type time.Time"
return "json: cannot unmarshal array into Go value of type time.Time"
} else {
return "Time.UnmarshalJSON: input is not a JSON string"
}