Skip to content

Commit fe3405a

Browse files
committed
feat: add support for inline struct tag option
1 parent 279389a commit fe3405a

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

encode_test.go

+58
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,64 @@ func TestAnonymousFields(t *testing.T) {
17031703
return S{}
17041704
},
17051705
want: `{}`,
1706+
}, {
1707+
// Structs with an inline tag option should be embedded.
1708+
label: "InlinedStruct",
1709+
makeInput: func() interface{} {
1710+
type (
1711+
S2 struct{ X int }
1712+
S struct {
1713+
S2 `json:",inline"`
1714+
}
1715+
)
1716+
return S{S2: S2{X: 1}}
1717+
},
1718+
want: `{"X":1}`,
1719+
}, {
1720+
// Pointers to structs with an inline tag option should be embedded.
1721+
label: "InlinedStructPointer",
1722+
makeInput: func() interface{} {
1723+
type (
1724+
S2 struct{ X int }
1725+
S struct {
1726+
*S2 `json:",inline"`
1727+
}
1728+
)
1729+
return S{S2: &S2{X: 1}}
1730+
},
1731+
want: `{"X":1}`,
1732+
}, {
1733+
// Non-anymous generic struct with an inline tag option should
1734+
// be embedded.
1735+
label: "InlinedStructGeneric",
1736+
makeInput: func() interface{} {
1737+
type (
1738+
S1 struct {
1739+
X int
1740+
}
1741+
S2 struct {
1742+
Y int
1743+
}
1744+
S[T any] struct {
1745+
Embedded T `json:",inline"`
1746+
S2
1747+
}
1748+
)
1749+
return S[S1]{Embedded: S1{X: 1}, S2: S2{Y: 2}}
1750+
},
1751+
want: `{"X":1,"Y":2}`,
1752+
}, {
1753+
// Non-struct with an inline tag option should be serialized
1754+
label: "InlinedStructPointer",
1755+
makeInput: func() interface{} {
1756+
type (
1757+
S struct {
1758+
X int `json:",inline"`
1759+
}
1760+
)
1761+
return S{X: 1}
1762+
},
1763+
want: `{"X":1}`,
17061764
}}
17071765

17081766
for i, tt := range tests {

internal/encoder/code.go

+3
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,9 @@ func isEmbeddedStruct(field *StructFieldCode) bool {
10151015
if !field.isAnonymous {
10161016
return false
10171017
}
1018+
if field.tag.IsInline {
1019+
return true
1020+
}
10181021
t := field.typ
10191022
if t.Kind() == reflect.Ptr {
10201023
t = t.Elem()

internal/encoder/compiler.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ func (c *Compiler) structFieldCode(structCode *StructCode, tag *runtime.StructTa
637637
key: tag.Key,
638638
tag: tag,
639639
offset: field.Offset,
640-
isAnonymous: field.Anonymous && !tag.IsTaggedKey && toElemType(fieldType).Kind() == reflect.Struct,
640+
isAnonymous: (field.Anonymous || tag.IsInline) && !tag.IsTaggedKey && toElemType(fieldType).Kind() == reflect.Struct,
641641
isTaggedKey: tag.IsTaggedKey,
642642
isNilableType: c.isNilableType(fieldType),
643643
isNilCheck: true,

internal/runtime/struct_field.go

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ func IsIgnoredStructField(field reflect.StructField) bool {
3131

3232
type StructTag struct {
3333
Key string
34+
IsInline bool
3435
IsTaggedKey bool
3536
IsOmitEmpty bool
3637
IsString bool
@@ -84,6 +85,8 @@ func StructTagFromField(field reflect.StructField) *StructTag {
8485
st.IsOmitEmpty = true
8586
case "string":
8687
st.IsString = true
88+
case "inline":
89+
st.IsInline = true
8790
}
8891
}
8992
}

0 commit comments

Comments
 (0)