Skip to content

Commit

Permalink
fix: fix apijson.Port for embedded structs (#3844)
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-app[bot] committed Jan 20, 2025
1 parent 600e8c6 commit 75a6433
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 13 deletions.
37 changes: 24 additions & 13 deletions internal/apijson/port.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,33 @@ func Port(from any, to any) error {
fromJSON := fromVal.FieldByName("JSON")
toJSON := toVal.FieldByName("JSON")

// First, iterate through the from fields and load all the "normal" fields in the struct to the map of
// string to reflect.Value, as well as their raw .JSON.Foo counterpart.
for i := 0; i < fromType.NumField(); i++ {
field := fromType.Field(i)
ptag, ok := parseJSONStructTag(field)
if !ok {
continue
}
if ptag.name == "-" {
continue
// Iterate through the fields of v and load all the "normal" fields in the struct to the map of
// string to reflect.Value, as well as their raw .JSON.Foo counterpart indicated by j.
var getFields func(t reflect.Type, v, j reflect.Value)
getFields = func(t reflect.Type, v, j reflect.Value) {
// Recurse into anonymous fields first, since the fields on the object should win over the fields in the
// embedded object.
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.Anonymous {
getFields(field.Type, v.Field(i), v.FieldByName("JSON"))
continue
}
}
values[ptag.name] = fromVal.Field(i)
if fromJSON.IsValid() {
fields[ptag.name] = fromJSON.FieldByName(field.Name)

for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
ptag, ok := parseJSONStructTag(field)
if !ok || ptag.name == "-" {
continue
}
values[ptag.name] = v.Field(i)
if j.IsValid() {
fields[ptag.name] = j.FieldByName(field.Name)
}
}
}
getFields(fromType, fromVal, fromJSON)

// Use the values from the previous step to populate the 'to' struct.
for i := 0; i < toType.NumField(); i++ {
Expand Down
76 changes: 76 additions & 0 deletions internal/apijson/port_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,37 @@ type CardMastercardData struct {
Bar int64 `json:"bar"`
}

type CommonFields struct {
Metadata Metadata `json:"metadata"`
Value string `json:"value"`
}

type commonFieldsJSON struct {
Metadata Field
Value Field
ExtraFields map[string]Field
}

type CardEmbedded struct {
CommonFields
Processor CardVisaProcessor `json:"processor"`
Data CardVisaData `json:"data"`
IsFoo bool `json:"is_foo"`

JSON cardEmbeddedJSON
}

type cardEmbeddedJSON struct {
commonFieldsJSON
Processor Field
Data Field
IsFoo Field
ExtraFields map[string]Field
raw string
}

func (r cardEmbeddedJSON) RawJSON() string { return r.raw }

var portTests = map[string]struct {
from any
to any
Expand Down Expand Up @@ -158,6 +189,51 @@ var portTests = map[string]struct {
Value: false,
},
},
"embedded to card": {
CardEmbedded{
CommonFields: CommonFields{
Metadata: Metadata{
CreatedAt: "Mar 29 2024",
},
Value: "embedded_value",
},
Processor: "visa",
IsFoo: true,
Data: CardVisaData{
Foo: "embedded_foo",
},
JSON: cardEmbeddedJSON{
commonFieldsJSON: commonFieldsJSON{
Metadata: Field{raw: `{"created_at":"Mar 29 2024"}`, status: valid},
Value: Field{raw: `"embedded_value"`, status: valid},
},
raw: `{"processor":"visa","is_foo":true,"data":{"foo":"embedded_foo"}}`,
Processor: Field{raw: `"visa"`, status: valid},
IsFoo: Field{raw: `true`, status: valid},
Data: Field{raw: `{"foo":"embedded_foo"}`, status: valid},
},
},
Card{
Processor: "visa",
IsFoo: true,
IsBar: false,
Data: CardVisaData{
Foo: "embedded_foo",
},
Metadata: Metadata{
CreatedAt: "Mar 29 2024",
},
Value: "embedded_value",
JSON: cardJSON{
raw: "{\"processor\":\"visa\",\"is_foo\":true,\"data\":{\"foo\":\"embedded_foo\"}}",
Processor: Field{raw: `"visa"`, status: 0x3},
IsFoo: Field{raw: "true", status: 0x3},
Data: Field{raw: `{"foo":"embedded_foo"}`, status: 0x3},
Metadata: Field{raw: `{"created_at":"Mar 29 2024"}`, status: 0x3},
Value: Field{raw: `"embedded_value"`, status: 0x3},
},
},
},
}

func TestPort(t *testing.T) {
Expand Down

0 comments on commit 75a6433

Please sign in to comment.