mirror of https://github.com/goccy/go-json.git
Merge branch 'goccy:master' into master
This commit is contained in:
commit
3aaec8ddc2
|
@ -13,12 +13,13 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
- name: build
|
||||
run: docker-compose run go-json
|
||||
|
||||
test:
|
||||
name: Test
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ "ubuntu-latest", "macos-latest", "windows-latest" ]
|
||||
go-version: [ "1.18", "1.19", "1.20" ]
|
||||
go-version: [ "1.19", "1.20", "1.21" ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: setup Go ${{ matrix.go-version }}
|
||||
|
@ -35,6 +36,20 @@ jobs:
|
|||
GOGC: 1
|
||||
- name: test with race detector
|
||||
run: go test -v -race ./... -count=1
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: setup Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.21'
|
||||
- name: lint
|
||||
run: |
|
||||
make lint
|
||||
bench:
|
||||
name: Benchmark
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -42,7 +57,7 @@ jobs:
|
|||
- name: setup Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: '1.21'
|
||||
- name: checkout ( feature )
|
||||
uses: actions/checkout@v3
|
||||
- name: run benchmark ( feature )
|
||||
|
@ -57,19 +72,21 @@ jobs:
|
|||
run: cd benchmarks && go test -bench GoJson | tee $HOME/old.txt
|
||||
- name: compare benchmark results
|
||||
run: benchstat $HOME/old.txt $HOME/new.txt
|
||||
|
||||
coverage:
|
||||
name: Coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: setup Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
go-version: '1.21'
|
||||
- name: measure coverage
|
||||
run: make cover
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v4
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
name: lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.45.2
|
||||
args: --timeout=5m
|
|
@ -56,6 +56,9 @@ linters:
|
|||
- cyclop
|
||||
- containedctx
|
||||
- revive
|
||||
- nosnakecase
|
||||
- exhaustruct
|
||||
- depguard
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
|
|
2
Makefile
2
Makefile
|
@ -30,7 +30,7 @@ golangci-lint: | $(BIN_DIR)
|
|||
GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
|
||||
cd $$GOLANGCI_LINT_TMP_DIR; \
|
||||
go mod init tmp; \
|
||||
GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.48.0; \
|
||||
GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2; \
|
||||
rm -rf $$GOLANGCI_LINT_TMP_DIR; \
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -56,7 +55,7 @@ func codeInit() {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data, err := ioutil.ReadAll(gz)
|
||||
data, err := io.ReadAll(gz)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -104,7 +103,7 @@ func Benchmark_EncodeBigData_GoJson(b *testing.B) {
|
|||
b.StartTimer()
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
enc := json.NewEncoder(ioutil.Discard)
|
||||
enc := json.NewEncoder(io.Discard)
|
||||
for pb.Next() {
|
||||
if err := enc.Encode(&codeStruct); err != nil {
|
||||
b.Fatal("Encode:", err)
|
||||
|
@ -122,7 +121,7 @@ func Benchmark_EncodeBigData_EncodingJson(b *testing.B) {
|
|||
b.StartTimer()
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
enc := stdjson.NewEncoder(ioutil.Discard)
|
||||
enc := stdjson.NewEncoder(io.Discard)
|
||||
for pb.Next() {
|
||||
if err := enc.Encode(&codeStruct); err != nil {
|
||||
b.Fatal("Encode:", err)
|
||||
|
@ -141,7 +140,7 @@ func Benchmark_EncodeBigData_JsonIter(b *testing.B) {
|
|||
}
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
enc := json.NewEncoder(ioutil.Discard)
|
||||
enc := json.NewEncoder(io.Discard)
|
||||
for pb.Next() {
|
||||
if err := enc.Encode(&codeStruct); err != nil {
|
||||
b.Fatal("Encode:", err)
|
||||
|
@ -159,7 +158,7 @@ func Benchmark_EncodeBigData_SegmentioJson(b *testing.B) {
|
|||
b.StartTimer()
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
enc := segmentiojson.NewEncoder(ioutil.Discard)
|
||||
enc := segmentiojson.NewEncoder(io.Discard)
|
||||
for pb.Next() {
|
||||
if err := enc.Encode(&codeStruct); err != nil {
|
||||
b.Fatal("Encode:", err)
|
||||
|
@ -316,7 +315,7 @@ func Benchmark_EncodeRawMessage_EncodingJson(b *testing.B) {
|
|||
}{}
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
enc := stdjson.NewEncoder(ioutil.Discard)
|
||||
enc := stdjson.NewEncoder(io.Discard)
|
||||
for pb.Next() {
|
||||
if err := enc.Encode(&m); err != nil {
|
||||
b.Fatal("Encode:", err)
|
||||
|
@ -336,7 +335,7 @@ func Benchmark_EncodeRawMessage_JsonIter(b *testing.B) {
|
|||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
enc := json.NewEncoder(ioutil.Discard)
|
||||
enc := json.NewEncoder(io.Discard)
|
||||
for pb.Next() {
|
||||
if err := enc.Encode(&m); err != nil {
|
||||
b.Fatal("Encode:", err)
|
||||
|
@ -353,7 +352,7 @@ func Benchmark_EncodeRawMessage_GoJson(b *testing.B) {
|
|||
B json.RawMessage
|
||||
}{}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
enc := json.NewEncoder(ioutil.Discard)
|
||||
enc := json.NewEncoder(io.Discard)
|
||||
for pb.Next() {
|
||||
if err := enc.Encode(&m); err != nil {
|
||||
b.Fatal("Encode:", err)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module benchmark
|
||||
|
||||
go 1.12
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/francoispqt/gojay v1.2.13
|
||||
|
@ -9,9 +9,14 @@ require (
|
|||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe
|
||||
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7
|
||||
github.com/segmentio/encoding v0.2.4
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
github.com/valyala/fastjson v1.6.3
|
||||
github.com/wI2L/jettison v0.7.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/goccy/go-json => ../
|
||||
|
|
|
@ -56,7 +56,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe h1:W/GaMY0y69G4cFlmsC6B9sbuo2fP8OFP1ABjt4kPz+w=
|
||||
|
@ -71,7 +70,6 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
|
|||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@ -182,7 +180,6 @@ google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9M
|
|||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -197,6 +197,13 @@ func Test_Decoder(t *testing.T) {
|
|||
assertEq(t, "interface{}", v.F, nil)
|
||||
assertEq(t, "nilfunc", true, v.G == nil)
|
||||
})
|
||||
t.Run("struct.pointer must be nil", func(t *testing.T) {
|
||||
var v struct {
|
||||
A *int
|
||||
}
|
||||
json.Unmarshal([]byte(`{"a": "alpha"}`), &v)
|
||||
assertEq(t, "struct.A", v.A, (*int)(nil))
|
||||
})
|
||||
})
|
||||
t.Run("interface", func(t *testing.T) {
|
||||
t.Run("number", func(t *testing.T) {
|
||||
|
|
|
@ -52,7 +52,7 @@ func (e *Encoder) EncodeContext(ctx context.Context, v interface{}, optFuncs ...
|
|||
rctx.Option.Flag |= encoder.ContextOption
|
||||
rctx.Option.Context = ctx
|
||||
|
||||
err := e.encodeWithOption(rctx, v, optFuncs...)
|
||||
err := e.encodeWithOption(rctx, v, optFuncs...) //nolint: contextcheck
|
||||
|
||||
encoder.ReleaseRuntimeContext(rctx)
|
||||
return err
|
||||
|
@ -120,7 +120,7 @@ func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOption
|
|||
optFunc(rctx.Option)
|
||||
}
|
||||
|
||||
buf, err := encode(rctx, v)
|
||||
buf, err := encode(rctx, v) //nolint: contextcheck
|
||||
if err != nil {
|
||||
encoder.ReleaseRuntimeContext(rctx)
|
||||
return nil, err
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
@ -273,11 +273,11 @@ func (t OpType) FieldToOmitEmptyField() OpType {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(path, buf, 0644)
|
||||
return os.WriteFile(path, buf, 0644)
|
||||
}
|
||||
|
||||
func generateVM() error {
|
||||
file, err := ioutil.ReadFile("vm.go.tmpl")
|
||||
file, err := os.ReadFile("vm.go.tmpl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ func generateVM() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(path, source, 0644); err != nil {
|
||||
if err := os.WriteFile(path, source, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P
|
|||
}
|
||||
c, err := d.dec.Decode(ctx, cursor, depth, newptr)
|
||||
if err != nil {
|
||||
*(*unsafe.Pointer)(p) = nil
|
||||
return 0, err
|
||||
}
|
||||
cursor = c
|
||||
|
|
|
@ -147,7 +147,7 @@ func (d *unmarshalTextDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int
|
|||
return nil, 0, fmt.Errorf("json: unmarshal text decoder does not support decode path")
|
||||
}
|
||||
|
||||
func unquoteBytes(s []byte) (t []byte, ok bool) {
|
||||
func unquoteBytes(s []byte) (t []byte, ok bool) { //nolint: nonamedreturns
|
||||
length := len(s)
|
||||
if length < 2 || s[0] != '"' || s[length-1] != '"' {
|
||||
return
|
||||
|
|
|
@ -213,8 +213,8 @@ func compactString(dst, src []byte, cursor int64, escape bool) ([]byte, int64, e
|
|||
dst = append(dst, src[start:cursor]...)
|
||||
dst = append(dst, `\u202`...)
|
||||
dst = append(dst, hex[src[cursor+2]&0xF])
|
||||
cursor += 2
|
||||
start = cursor + 3
|
||||
cursor += 2
|
||||
}
|
||||
}
|
||||
switch c {
|
||||
|
|
|
@ -480,7 +480,7 @@ func (c *Compiler) mapCode(typ *runtime.Type) (*MapCode, error) {
|
|||
|
||||
func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) {
|
||||
switch {
|
||||
case c.isPtrMarshalJSONType(typ):
|
||||
case c.implementsMarshalJSONType(typ) || c.implementsMarshalJSONType(runtime.PtrTo(typ)):
|
||||
return c.marshalJSONCode(typ)
|
||||
case !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType):
|
||||
return c.marshalTextCode(typ)
|
||||
|
|
|
@ -1,3 +1,27 @@
|
|||
// This files's processing codes are inspired by https://github.com/segmentio/encoding.
|
||||
// The license notation is as follows.
|
||||
//
|
||||
// # MIT License
|
||||
//
|
||||
// Copyright (c) 2019 Segment.io, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
package encoder
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,27 @@
|
|||
// This files's string processing codes are inspired by https://github.com/segmentio/encoding.
|
||||
// The license notation is as follows.
|
||||
//
|
||||
// # MIT License
|
||||
//
|
||||
// Copyright (c) 2019 Segment.io, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
package encoder
|
||||
|
||||
import (
|
||||
|
|
|
@ -252,7 +252,6 @@ func IfaceIndir(*Type) bool
|
|||
//go:noescape
|
||||
func RType2Type(t *Type) reflect.Type
|
||||
|
||||
//go:nolint structcheck
|
||||
type emptyInterface struct {
|
||||
_ *Type
|
||||
ptr unsafe.Pointer
|
||||
|
|
35
json.go
35
json.go
|
@ -89,31 +89,31 @@ type UnmarshalerContext interface {
|
|||
//
|
||||
// Examples of struct field tags and their meanings:
|
||||
//
|
||||
// // Field appears in JSON as key "myName".
|
||||
// Field int `json:"myName"`
|
||||
// // Field appears in JSON as key "myName".
|
||||
// Field int `json:"myName"`
|
||||
//
|
||||
// // Field appears in JSON as key "myName" and
|
||||
// // the field is omitted from the object if its value is empty,
|
||||
// // as defined above.
|
||||
// Field int `json:"myName,omitempty"`
|
||||
// // Field appears in JSON as key "myName" and
|
||||
// // the field is omitted from the object if its value is empty,
|
||||
// // as defined above.
|
||||
// Field int `json:"myName,omitempty"`
|
||||
//
|
||||
// // Field appears in JSON as key "Field" (the default), but
|
||||
// // the field is skipped if empty.
|
||||
// // Note the leading comma.
|
||||
// Field int `json:",omitempty"`
|
||||
// // Field appears in JSON as key "Field" (the default), but
|
||||
// // the field is skipped if empty.
|
||||
// // Note the leading comma.
|
||||
// Field int `json:",omitempty"`
|
||||
//
|
||||
// // Field is ignored by this package.
|
||||
// Field int `json:"-"`
|
||||
// // Field is ignored by this package.
|
||||
// Field int `json:"-"`
|
||||
//
|
||||
// // Field appears in JSON as key "-".
|
||||
// Field int `json:"-,"`
|
||||
// // Field appears in JSON as key "-".
|
||||
// Field int `json:"-,"`
|
||||
//
|
||||
// The "string" option signals that a field is stored as JSON inside a
|
||||
// JSON-encoded string. It applies only to fields of string, floating point,
|
||||
// integer, or boolean types. This extra level of encoding is sometimes used
|
||||
// when communicating with JavaScript programs:
|
||||
//
|
||||
// Int64String int64 `json:",string"`
|
||||
// Int64String int64 `json:",string"`
|
||||
//
|
||||
// The key name will be used if it's a non-empty string consisting of
|
||||
// only Unicode letters, digits, and ASCII punctuation except quotation
|
||||
|
@ -166,7 +166,6 @@ type UnmarshalerContext interface {
|
|||
// JSON cannot represent cyclic data structures and Marshal does not
|
||||
// handle them. Passing cyclic structures to Marshal will result in
|
||||
// an infinite recursion.
|
||||
//
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
return MarshalWithOption(v)
|
||||
}
|
||||
|
@ -264,14 +263,13 @@ func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...E
|
|||
//
|
||||
// The JSON null value unmarshals into an interface, map, pointer, or slice
|
||||
// by setting that Go value to nil. Because null is often used in JSON to mean
|
||||
// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
|
||||
// “not present,” unmarshaling a JSON null into any other Go type has no effect
|
||||
// on the value and produces no error.
|
||||
//
|
||||
// When unmarshaling quoted strings, invalid UTF-8 or
|
||||
// invalid UTF-16 surrogate pairs are not treated as an error.
|
||||
// Instead, they are replaced by the Unicode replacement
|
||||
// character U+FFFD.
|
||||
//
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
return unmarshal(data, v)
|
||||
}
|
||||
|
@ -299,7 +297,6 @@ func UnmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc)
|
|||
// Number, for JSON numbers
|
||||
// string, for JSON string literals
|
||||
// nil, for JSON null
|
||||
//
|
||||
type Token = json.Token
|
||||
|
||||
// A Number represents a JSON number literal.
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -234,7 +233,7 @@ func TestDecoderBuffered(t *testing.T) {
|
|||
if m.Name != "Gopher" {
|
||||
t.Errorf("Name = %q; want Gopher", m.Name)
|
||||
}
|
||||
rest, err := ioutil.ReadAll(d.Buffered())
|
||||
rest, err := io.ReadAll(d.Buffered())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,18 @@ func (coverSliceMarshalJSON) MarshalJSON() ([]byte, error) {
|
|||
return []byte(`"hello"`), nil
|
||||
}
|
||||
|
||||
type coverSliceMarshalJSONMap map[string]any
|
||||
|
||||
func (c coverSliceMarshalJSONMap) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(map[string]any(c))
|
||||
}
|
||||
|
||||
type coverSliceMarshalJSONMapPtr map[string]any
|
||||
|
||||
func (c *coverSliceMarshalJSONMapPtr) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(map[string]any(*c))
|
||||
}
|
||||
|
||||
type coverSliceMarshalText struct {
|
||||
A int
|
||||
}
|
||||
|
@ -152,6 +164,22 @@ func TestCoverSlice(t *testing.T) {
|
|||
name: "SliceMarshalJSON",
|
||||
data: []coverSliceMarshalJSON{{A: 1}, {A: 2}},
|
||||
},
|
||||
{
|
||||
name: "SliceMarshalJSONMap",
|
||||
data: []coverSliceMarshalJSONMap{{"foo": "bar"}, {"some": 1}},
|
||||
},
|
||||
{
|
||||
name: "SliceMarshalJSONMap",
|
||||
data: []*coverSliceMarshalJSONMap{{"foo": "bar"}, {"some": 1}},
|
||||
},
|
||||
{
|
||||
name: "SliceMarshalJSONMap",
|
||||
data: []coverSliceMarshalJSONMapPtr{{"foo": "bar"}, {"some": 1}},
|
||||
},
|
||||
{
|
||||
name: "SliceMarshalJSONMap",
|
||||
data: []*coverSliceMarshalJSONMapPtr{{"foo": "bar"}, {"some": 1}},
|
||||
},
|
||||
{
|
||||
name: "SliceMarshalText",
|
||||
data: []coverSliceMarshalText{{A: 1}, {A: 2}},
|
||||
|
|
Loading…
Reference in New Issue