aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding/json')
-rw-r--r--src/encoding/json/decode.go10
-rw-r--r--src/encoding/json/encode.go43
-rw-r--r--src/encoding/json/encode_test.go2
3 files changed, 44 insertions, 11 deletions
diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go
index ce566f7955..efceecdf82 100644
--- a/src/encoding/json/decode.go
+++ b/src/encoding/json/decode.go
@@ -17,6 +17,7 @@ import (
"unicode"
"unicode/utf16"
"unicode/utf8"
+ _ "unsafe" // for linkname
)
// Unmarshal parses the JSON-encoded data and stores the result
@@ -1178,6 +1179,15 @@ func unquote(s []byte) (t string, ok bool) {
return
}
+// unquoteBytes should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/bytedance/sonic
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname unquoteBytes
func unquoteBytes(s []byte) (t []byte, ok bool) {
if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
return
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go
index 0035a65cfc..cb28feb279 100644
--- a/src/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -12,18 +12,19 @@ package json
import (
"bytes"
+ "cmp"
"encoding"
"encoding/base64"
"fmt"
"math"
"reflect"
"slices"
- "sort"
"strconv"
"strings"
"sync"
"unicode"
"unicode/utf8"
+ _ "unsafe" // for linkname
)
// Marshal returns the JSON encoding of v.
@@ -591,6 +592,16 @@ func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
}
// isValidNumber reports whether s is a valid JSON number literal.
+//
+// isValidNumber should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/bytedance/sonic
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname isValidNumber
func isValidNumber(s string) bool {
// This function implements the JSON numbers grammar.
// See https://tools.ietf.org/html/rfc7159#section-6
@@ -1045,6 +1056,16 @@ type field struct {
// typeFields returns a list of fields that JSON should recognize for the given type.
// The algorithm is breadth-first search over the set of structs to include - the top struct
// and then any reachable anonymous structs.
+//
+// typeFields should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/bytedance/sonic
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname typeFields
func typeFields(t reflect.Type) structFields {
// Anonymous fields to explore at the current level and the next.
current := []field{}
@@ -1162,21 +1183,23 @@ func typeFields(t reflect.Type) structFields {
}
}
- sort.Slice(fields, func(i, j int) bool {
- x := fields
+ slices.SortFunc(fields, func(a, b field) int {
// sort field by name, breaking ties with depth, then
// breaking ties with "name came from json tag", then
// breaking ties with index sequence.
- if x[i].name != x[j].name {
- return x[i].name < x[j].name
+ if c := strings.Compare(a.name, b.name); c != 0 {
+ return c
}
- if len(x[i].index) != len(x[j].index) {
- return len(x[i].index) < len(x[j].index)
+ if c := cmp.Compare(len(a.index), len(b.index)); c != 0 {
+ return c
}
- if x[i].tag != x[j].tag {
- return x[i].tag
+ if a.tag != b.tag {
+ if a.tag {
+ return -1
+ }
+ return +1
}
- return slices.Compare(x[i].index, x[j].index) == -1
+ return slices.Compare(a.index, b.index)
})
// Delete all fields that are hidden by the Go rules for embedded fields,
diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go
index 53259f4a9b..23a14d0b17 100644
--- a/src/encoding/json/encode_test.go
+++ b/src/encoding/json/encode_test.go
@@ -1168,7 +1168,7 @@ func TestMarshalUncommonFieldNames(t *testing.T) {
func TestMarshalerError(t *testing.T) {
s := "test variable"
st := reflect.TypeOf(s)
- errText := "json: test error"
+ const errText = "json: test error"
tests := []struct {
CaseName