Skip to content

Commit

Permalink
encoder
Browse files Browse the repository at this point in the history
  • Loading branch information
AsterDY committed Aug 1, 2024
1 parent c00f19a commit 4158fff
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 56 deletions.
1 change: 0 additions & 1 deletion go1.23
Submodule go1.23 deleted from c9940f
25 changes: 20 additions & 5 deletions internal/encoder/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,31 +127,40 @@ func (self *Compiler) compileOne(p *ir.Program, sp int, vt reflect.Type, pv bool
}
}

func (self *Compiler) compileRec(p *ir.Program, sp int, vt reflect.Type, pv bool) {
pr := self.pv
func (self *Compiler) tryCompileMarshaler(p *ir.Program, vt reflect.Type, pv bool) bool {
pt := reflect.PtrTo(vt)

/* check for addressable `json.Marshaler` with pointer receiver */
if pv && pt.Implements(vars.JsonMarshalerType) {
addMarshalerOp(p, ir.OP_marshal_p, pt, vars.JsonMarshalerType)
return
return true
}

/* check for `json.Marshaler` */
if vt.Implements(vars.JsonMarshalerType) {
self.compileMarshaler(p, ir.OP_marshal, vt, vars.JsonMarshalerType)
return
return true
}

/* check for addressable `encoding.TextMarshaler` with pointer receiver */
if pv && pt.Implements(vars.EncodingTextMarshalerType) {
addMarshalerOp(p, ir.OP_marshal_text_p, pt, vars.EncodingTextMarshalerType)
return
return true
}

/* check for `encoding.TextMarshaler` */
if vt.Implements(vars.EncodingTextMarshalerType) {
self.compileMarshaler(p, ir.OP_marshal_text, vt, vars.EncodingTextMarshalerType)
return true
}

return false
}

func (self *Compiler) compileRec(p *ir.Program, sp int, vt reflect.Type, pv bool) {
pr := self.pv

if self.tryCompileMarshaler(p, vt, pv) {
return
}

Expand Down Expand Up @@ -485,6 +494,12 @@ func (self *Compiler) compileStructBody(p *ir.Program, sp int, vt reflect.Type)
}

func (self *Compiler) compileStructFieldStr(p *ir.Program, sp int, vt reflect.Type) {
// NOTICE: according to encoding/json, Marshaler type has higher priority than string option
// see issue:
if self.tryCompileMarshaler(p, vt, self.pv) {
return
}

pc := -1
ft := vt
sv := false
Expand Down
50 changes: 0 additions & 50 deletions issue_test/race_test_go

This file was deleted.

86 changes: 86 additions & 0 deletions issue_test/xx/xx_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2024 CloudWeGo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package issue_test

import (
"encoding/json"
"fmt"
"testing"
"time"

"github.com/bytedance/sonic"
"github.com/stretchr/testify/assert"
)

func TestX(t *testing.T) {
// var obj = Issue670Case{ D: Date(time.Now().Unix()) }
// so, _ := sonic.MarshalString(obj)
// eo, _ := json.Marshal(obj)
// assert.Equal(t, string(eo), so)
// println(string(eo))

// match
eo := []byte(`{"D":"2021-08-26","E":1}`)
testUnmarshal(t, eo)

// // mismatch
// eo = []byte(`{"D":11,"E":1}`)
// testUnmarshal(t, eo)

// // null
// eo = []byte(`{"D":null,"E":1}`)
// testUnmarshal(t, eo)
}

func testUnmarshal(t *testing.T, eo []byte) {
obj := Issue670Case{}
println(string(eo))
println("sonic")
es := sonic.Unmarshal(eo, &obj)
obj2 := Issue670Case{}
println("std")
ee := json.Unmarshal(eo, &obj2)
assert.Equal(t, ee ==nil, es == nil, es)
assert.Equal(t, obj2, obj)
fmt.Printf("error: %v, obj: %#v", ee, obj2)
}

type Issue670Case struct {
D Date `form:"D" json:"D,string" query:"D"`
E int
}

type Date int64

func (d Date) MarshalJSON() ([]byte, error) {
if d == 0 {
return []byte("null"), nil
}
return []byte(fmt.Sprintf("\"%s\"", time.Unix(int64(d), 0).Format("2006-01-02"))), nil
}

func (d *Date) UnmarshalJSON(in []byte) error {
if string(in) == "null" {
*d = 0
return nil
}
println("hook ", string(in))
t, err := time.Parse("2006-01-02", string(in))
if err != nil {
return err
}
*d = Date(t.Unix())
return nil
}

0 comments on commit 4158fff

Please sign in to comment.