Compare commits

...

4 Commits

Author SHA1 Message Date
runcong zhang 744d40e437
Merge 40080c2aaf into 3e9769d637 2024-11-22 06:54:38 +00:00
Masaaki Goshima 3e9769d637
Update go.yml 2024-11-11 12:13:39 +09:00
Andrey Grazhdankov 65c8b28ca1
Fix encode []*time.Time - check nil (#524) 2024-11-11 11:10:21 +09:00
runcong zhang 40080c2aaf feat:add map and array filter code 2023-08-04 22:30:58 +08:00
6 changed files with 96 additions and 6 deletions

View File

@ -12,7 +12,7 @@ jobs:
- name: checkout
uses: actions/checkout@v3
- name: build
run: docker-compose run go-json
run: docker compose run go-json
test:
name: Test

View File

@ -426,6 +426,11 @@ func Test_Marshal(t *testing.T) {
assertErr(t, err)
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) {

View File

@ -271,7 +271,13 @@ func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes {
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
}
@ -316,7 +322,13 @@ func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
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
}
@ -366,7 +378,14 @@ func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
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
}

View File

@ -406,6 +406,11 @@ func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{
rv = newV
}
}
if rv.Kind() == reflect.Ptr && rv.IsNil() {
return AppendNull(ctx, b), nil
}
v = rv.Interface()
var bb []byte
if (code.Flags & MarshalerContextFlags) != 0 {

View File

@ -203,6 +203,9 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
}
}
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)))
if err != nil {
return nil, err

View File

@ -28,6 +28,20 @@ type queryTestZ struct {
ZA string
ZB bool
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) {
@ -45,6 +59,10 @@ func TestFieldQuery(t *testing.T) {
json.BuildSubFieldQuery("YC").Fields(
"ZA",
"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: "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 {
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)
}
ctx := json.SetFieldQueryToContext(context.Background(), query)
@ -103,6 +153,14 @@ func TestFieldQuery(t *testing.T) {
ZA: "za",
ZB: true,
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,
YE: 4,
@ -113,7 +171,7 @@ func TestFieldQuery(t *testing.T) {
if err != nil {
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)
if expected != got {
t.Fatalf("failed to encode with field query: expected %q but got %q", expected, got)