fix: determining embedded structs was wrong

fix #362
This commit is contained in:
Nao Yonashiro 2022-04-26 14:16:28 +09:00
parent 6911114fb4
commit af33c47846
4 changed files with 43 additions and 3 deletions

View File

@ -3944,3 +3944,18 @@ func TestIssue364(t *testing.T) {
t.Errorf("unexpected result: %v", v.Description) t.Errorf("unexpected result: %v", v.Description)
} }
} }
func TestIssue362(t *testing.T) {
type AliasedPrimitive int
type Combiner struct {
SomeField int
AliasedPrimitive
}
originalCombiner := Combiner{AliasedPrimitive: 7}
b, err := json.Marshal(originalCombiner)
assertErr(t, err)
newCombiner := Combiner{}
err = json.Unmarshal(b, &newCombiner)
assertErr(t, err)
assertEq(t, "TestEmbeddedPrimitiveAlias", originalCombiner, newCombiner)
}

View File

@ -394,6 +394,15 @@ func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeTo
allFields = append(allFields, fieldSet) allFields = append(allFields, fieldSet)
} }
} }
} else {
fieldSet := &structFieldSet{
dec: dec,
offset: field.Offset,
isTaggedKey: tag.IsTaggedKey,
key: field.Name,
keyLen: int64(len(field.Name)),
}
allFields = append(allFields, fieldSet)
} }
} else { } else {
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) { if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {

View File

@ -2,6 +2,7 @@ package encoder
import ( import (
"fmt" "fmt"
"reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "github.com/goccy/go-json/internal/runtime"
@ -383,7 +384,7 @@ func (c *StructCode) Kind() CodeKind {
} }
func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode { func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode {
if field.isAnonymous { if isEmbeddedStruct(field) {
return c.lastAnonymousFieldCode(firstField) return c.lastAnonymousFieldCode(firstField)
} }
lastField := firstField lastField := firstField
@ -436,7 +437,7 @@ func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
} }
if isEndField { if isEndField {
endField := fieldCodes.Last() endField := fieldCodes.Last()
if field.isAnonymous { if isEmbeddedStruct(field) {
firstField.End = endField firstField.End = endField
lastField := c.lastAnonymousFieldCode(firstField) lastField := c.lastAnonymousFieldCode(firstField)
lastField.NextField = endField lastField.NextField = endField
@ -1003,3 +1004,14 @@ func convertPtrOp(code *Opcode) OpType {
} }
return code.Op return code.Op
} }
func isEmbeddedStruct(field *StructFieldCode) bool {
if !field.isAnonymous {
return false
}
t := field.typ
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
return t.Kind() == reflect.Struct
}

View File

@ -13,7 +13,11 @@ func getTag(field reflect.StructField) string {
func IsIgnoredStructField(field reflect.StructField) bool { func IsIgnoredStructField(field reflect.StructField) bool {
if field.PkgPath != "" { if field.PkgPath != "" {
if field.Anonymous { if field.Anonymous {
if !(field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct) && field.Type.Kind() != reflect.Struct { t := field.Type
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if !field.IsExported() && t.Kind() != reflect.Struct {
return true return true
} }
} else { } else {