Skip to content

Commit af33c47

Browse files
committed
fix: determining embedded structs was wrong
fix goccy#362
1 parent 6911114 commit af33c47

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

decode_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3944,3 +3944,18 @@ func TestIssue364(t *testing.T) {
39443944
t.Errorf("unexpected result: %v", v.Description)
39453945
}
39463946
}
3947+
3948+
func TestIssue362(t *testing.T) {
3949+
type AliasedPrimitive int
3950+
type Combiner struct {
3951+
SomeField int
3952+
AliasedPrimitive
3953+
}
3954+
originalCombiner := Combiner{AliasedPrimitive: 7}
3955+
b, err := json.Marshal(originalCombiner)
3956+
assertErr(t, err)
3957+
newCombiner := Combiner{}
3958+
err = json.Unmarshal(b, &newCombiner)
3959+
assertErr(t, err)
3960+
assertEq(t, "TestEmbeddedPrimitiveAlias", originalCombiner, newCombiner)
3961+
}

internal/decoder/compile.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,15 @@ func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeTo
394394
allFields = append(allFields, fieldSet)
395395
}
396396
}
397+
} else {
398+
fieldSet := &structFieldSet{
399+
dec: dec,
400+
offset: field.Offset,
401+
isTaggedKey: tag.IsTaggedKey,
402+
key: field.Name,
403+
keyLen: int64(len(field.Name)),
404+
}
405+
allFields = append(allFields, fieldSet)
397406
}
398407
} else {
399408
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {

internal/encoder/code.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package encoder
22

33
import (
44
"fmt"
5+
"reflect"
56
"unsafe"
67

78
"github.com/goccy/go-json/internal/runtime"
@@ -383,7 +384,7 @@ func (c *StructCode) Kind() CodeKind {
383384
}
384385

385386
func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode {
386-
if field.isAnonymous {
387+
if isEmbeddedStruct(field) {
387388
return c.lastAnonymousFieldCode(firstField)
388389
}
389390
lastField := firstField
@@ -436,7 +437,7 @@ func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
436437
}
437438
if isEndField {
438439
endField := fieldCodes.Last()
439-
if field.isAnonymous {
440+
if isEmbeddedStruct(field) {
440441
firstField.End = endField
441442
lastField := c.lastAnonymousFieldCode(firstField)
442443
lastField.NextField = endField
@@ -1003,3 +1004,14 @@ func convertPtrOp(code *Opcode) OpType {
10031004
}
10041005
return code.Op
10051006
}
1007+
1008+
func isEmbeddedStruct(field *StructFieldCode) bool {
1009+
if !field.isAnonymous {
1010+
return false
1011+
}
1012+
t := field.typ
1013+
if t.Kind() == reflect.Pointer {
1014+
t = t.Elem()
1015+
}
1016+
return t.Kind() == reflect.Struct
1017+
}

internal/runtime/struct_field.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ func getTag(field reflect.StructField) string {
1313
func IsIgnoredStructField(field reflect.StructField) bool {
1414
if field.PkgPath != "" {
1515
if field.Anonymous {
16-
if !(field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct) && field.Type.Kind() != reflect.Struct {
16+
t := field.Type
17+
if t.Kind() == reflect.Ptr {
18+
t = t.Elem()
19+
}
20+
if !field.IsExported() && t.Kind() != reflect.Struct {
1721
return true
1822
}
1923
} else {

0 commit comments

Comments
 (0)