mirror of https://github.com/goccy/go-json.git
Compare commits
4 Commits
1badc6c983
...
744d40e437
Author | SHA1 | Date |
---|---|---|
runcong zhang | 744d40e437 | |
Masaaki Goshima | 3e9769d637 | |
Andrey Grazhdankov | 65c8b28ca1 | |
runcong zhang | 40080c2aaf |
|
@ -12,7 +12,7 @@ jobs:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: build
|
- name: build
|
||||||
run: docker-compose run go-json
|
run: docker compose run go-json
|
||||||
|
|
||||||
test:
|
test:
|
||||||
name: Test
|
name: Test
|
||||||
|
|
|
@ -426,6 +426,11 @@ func Test_Marshal(t *testing.T) {
|
||||||
assertErr(t, err)
|
assertErr(t, err)
|
||||||
assertEq(t, "[]interface{}", `[1,2.1,"hello"]`, string(bytes))
|
assertEq(t, "[]interface{}", `[1,2.1,"hello"]`, string(bytes))
|
||||||
})
|
})
|
||||||
|
t.Run("[]*time.Time", func(t *testing.T) {
|
||||||
|
bytes, err := json.Marshal([]*time.Time{nil})
|
||||||
|
assertErr(t, err)
|
||||||
|
assertEq(t, "[]*time.Time", `[null]`, string(bytes))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("array", func(t *testing.T) {
|
t.Run("array", func(t *testing.T) {
|
||||||
|
|
|
@ -271,7 +271,13 @@ func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
|
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SliceCode) Filter(_ *FieldQuery) Code {
|
func (c *SliceCode) Filter(fieldQuery *FieldQuery) Code {
|
||||||
|
if len(fieldQuery.Fields) > 0 && fieldQuery.Fields[0].Name == "#" {
|
||||||
|
return &SliceCode{
|
||||||
|
value: c.value.Filter(fieldQuery.Fields[0]),
|
||||||
|
typ: c.typ,
|
||||||
|
}
|
||||||
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +322,13 @@ func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
|
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ArrayCode) Filter(_ *FieldQuery) Code {
|
func (c *ArrayCode) Filter(fieldQuery *FieldQuery) Code {
|
||||||
|
if len(fieldQuery.Fields) > 0 && fieldQuery.Fields[0].Name == "#" {
|
||||||
|
return &ArrayCode{
|
||||||
|
value: c.value.Filter(fieldQuery.Fields[0]),
|
||||||
|
typ: c.typ,
|
||||||
|
}
|
||||||
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +378,14 @@ func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end)
|
return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MapCode) Filter(_ *FieldQuery) Code {
|
func (c *MapCode) Filter(fieldQuery *FieldQuery) Code {
|
||||||
|
if len(fieldQuery.Fields) > 0 && fieldQuery.Fields[0].Name == "#" {
|
||||||
|
return &MapCode{
|
||||||
|
value: c.value.Filter(fieldQuery.Fields[0]),
|
||||||
|
typ: c.typ,
|
||||||
|
key: c.key,
|
||||||
|
}
|
||||||
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -406,6 +406,11 @@ func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{
|
||||||
rv = newV
|
rv = newV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rv.Kind() == reflect.Ptr && rv.IsNil() {
|
||||||
|
return AppendNull(ctx, b), nil
|
||||||
|
}
|
||||||
|
|
||||||
v = rv.Interface()
|
v = rv.Interface()
|
||||||
var bb []byte
|
var bb []byte
|
||||||
if (code.Flags & MarshalerContextFlags) != 0 {
|
if (code.Flags & MarshalerContextFlags) != 0 {
|
||||||
|
|
|
@ -203,6 +203,9 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, up)
|
ctx.KeepRefs = append(ctx.KeepRefs, up)
|
||||||
|
if code.FieldQuery != nil {
|
||||||
|
ctx.Option.Context = encoder.SetFieldQueryToContext(ctx.Option.Context, code.FieldQuery)
|
||||||
|
}
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ)))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -28,6 +28,20 @@ type queryTestZ struct {
|
||||||
ZA string
|
ZA string
|
||||||
ZB bool
|
ZB bool
|
||||||
ZC int
|
ZC int
|
||||||
|
ZD []queryTestW
|
||||||
|
ZE map[string]queryTestV
|
||||||
|
}
|
||||||
|
|
||||||
|
type queryTestW struct {
|
||||||
|
WA string
|
||||||
|
WB bool
|
||||||
|
WC int
|
||||||
|
}
|
||||||
|
|
||||||
|
type queryTestV struct {
|
||||||
|
VA string
|
||||||
|
VB bool
|
||||||
|
VC int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *queryTestZ) MarshalJSON(ctx context.Context) ([]byte, error) {
|
func (z *queryTestZ) MarshalJSON(ctx context.Context) ([]byte, error) {
|
||||||
|
@ -45,6 +59,10 @@ func TestFieldQuery(t *testing.T) {
|
||||||
json.BuildSubFieldQuery("YC").Fields(
|
json.BuildSubFieldQuery("YC").Fields(
|
||||||
"ZA",
|
"ZA",
|
||||||
"ZB",
|
"ZB",
|
||||||
|
json.BuildSubFieldQuery("ZD").Fields(json.BuildSubFieldQuery("#").Fields(
|
||||||
|
"WA", "WC")),
|
||||||
|
json.BuildSubFieldQuery("ZE").Fields(json.BuildSubFieldQuery("#").Fields(
|
||||||
|
"VA", "VC")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -77,6 +95,38 @@ func TestFieldQuery(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "ZB",
|
Name: "ZB",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "ZD",
|
||||||
|
Fields: []*json.FieldQuery{
|
||||||
|
{
|
||||||
|
Name: "#",
|
||||||
|
Fields: []*json.FieldQuery{
|
||||||
|
{
|
||||||
|
Name: "WA",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "WC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ZE",
|
||||||
|
Fields: []*json.FieldQuery{
|
||||||
|
{
|
||||||
|
Name: "#",
|
||||||
|
Fields: []*json.FieldQuery{
|
||||||
|
{
|
||||||
|
Name: "VA",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "VC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -89,7 +139,7 @@ func TestFieldQuery(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if queryStr != `["XA","XB",{"XC":["YA","YB",{"YC":["ZA","ZB"]}]}]` {
|
if queryStr != `["XA","XB",{"XC":["YA","YB",{"YC":["ZA","ZB",{"ZD":[{"#":["WA","WC"]}]},{"ZE":[{"#":["VA","VC"]}]}]}]}]` {
|
||||||
t.Fatalf("failed to create query string. %s", queryStr)
|
t.Fatalf("failed to create query string. %s", queryStr)
|
||||||
}
|
}
|
||||||
ctx := json.SetFieldQueryToContext(context.Background(), query)
|
ctx := json.SetFieldQueryToContext(context.Background(), query)
|
||||||
|
@ -103,6 +153,14 @@ func TestFieldQuery(t *testing.T) {
|
||||||
ZA: "za",
|
ZA: "za",
|
||||||
ZB: true,
|
ZB: true,
|
||||||
ZC: 3,
|
ZC: 3,
|
||||||
|
ZD: []queryTestW{
|
||||||
|
{WA: "wa1", WB: true, WC: 1},
|
||||||
|
{WA: "wa2", WB: true, WC: 1},
|
||||||
|
},
|
||||||
|
ZE: map[string]queryTestV{
|
||||||
|
"key1": {VA: "va1", VB: true, VC: 1},
|
||||||
|
"key2": {VA: "va2", VB: true, VC: 1},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
YD: true,
|
YD: true,
|
||||||
YE: 4,
|
YE: 4,
|
||||||
|
@ -113,7 +171,7 @@ func TestFieldQuery(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
expected := `{"XA":1,"XB":"xb","XC":{"YA":2,"YB":"yb","YC":{"ZA":"za","ZB":true}}}`
|
expected := `{"XA":1,"XB":"xb","XC":{"YA":2,"YB":"yb","YC":{"ZA":"za","ZB":true,"ZD":[{"WA":"wa1","WC":1},{"WA":"wa2","WC":1}],"ZE":{"key1":{"VA":"va1","VC":1},"key2":{"VA":"va2","VC":1}}}}}`
|
||||||
got := string(b)
|
got := string(b)
|
||||||
if expected != got {
|
if expected != got {
|
||||||
t.Fatalf("failed to encode with field query: expected %q but got %q", expected, got)
|
t.Fatalf("failed to encode with field query: expected %q but got %q", expected, got)
|
||||||
|
|
Loading…
Reference in New Issue