Skip to content

Commit

Permalink
fix: bring back json marshal support for ftl.Option (#1448)
Browse files Browse the repository at this point in the history
We used to support ftl.Option in normal json decoding, but was removed
here in this PR: [feat: Handle sum types in backend encoder
(](76ae43c)

Now the issue is this use case that PFI has: They make external API
requests and unmarshal the responses into ftl types, like this one:
```
type RecipientAddressResponse struct {
	ID          uuid.UUID                 `json:"id"`
	Chain       Chain                     `json:"chain"`
	Address     string                    `json:"address"`
	Description string                    `json:"description"`
	AddressTag  ftl.Option[string]        `json:"addressTag,omitempty"`
	Currency    ftl.Option[Currency]      `json:"currency"`
	Status      BizRecipientAddressStatus `json:"status"`
}
```
Which means after upgrading ftl a lot of their tests start failing:
```
=== RUN   TestListAllRecipientAddresses/good
    /Users/mtoohey/Code/pfi/backend/modules/moneymovements/circle/circle_test.go:97: Unexpected error: failed to unmarshal response body: json: cannot unmarshal string into Go struct field RecipientAddressResponse.data.currency of type ftl.Option[ftl/moneymovements/circle.Currency]
        failed to unmarshal response body: json: cannot unmarshal string into Go struct field RecipientAddressResponse.data.currency of type ftl.Option[ftl/moneymovements/circle.Currency]
--- FAIL: TestListAllRecipientAddresses (0.30s)
    --- FAIL: TestListAllRecipientAddresses/good (0.29s)
```

I'm a bit confused about all the different marshalling cases we need to
support now and whether this is the right fix...

With this PR, pfi's tests all work again
  • Loading branch information
matt2e authored May 9, 2024
1 parent 52c608f commit 4541116
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions go-runtime/ftl/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,25 @@ func (o Option[T]) Default(value T) T {
return value
}

func (o Option[T]) MarshalJSON() ([]byte, error) {
if o.ok {
return json.Marshal(o.value)
}
return []byte("null"), nil
}

func (o *Option[T]) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
o.ok = false
return nil
}
if err := json.Unmarshal(data, &o.value); err != nil {
return err
}
o.ok = true
return nil
}

func (o Option[T]) String() string {
if o.ok {
return fmt.Sprintf("%v", o.value)
Expand Down

0 comments on commit 4541116

Please sign in to comment.