From d684e27591e9af476da53bd9483a9ab37b85a483 Mon Sep 17 00:00:00 2001 From: Daniel Cohen <4705646+dacohen@users.noreply.github.com> Date: Sun, 26 Feb 2023 11:47:15 -0500 Subject: [PATCH] Support number/string agnostic JSON decoding (#24) --- amount.go | 14 ++++++++++---- amount_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/amount.go b/amount.go index dee3515..1d1e2d7 100644 --- a/amount.go +++ b/amount.go @@ -315,16 +315,22 @@ func (a Amount) MarshalJSON() ([]byte, error) { // UnmarshalJSON implements the json.Unmarshaler interface. func (a *Amount) UnmarshalJSON(data []byte) error { aux := struct { - Number string `json:"number"` - CurrencyCode string `json:"currency"` + Number json.RawMessage `json:"number"` + CurrencyCode string `json:"currency"` }{} err := json.Unmarshal(data, &aux) if err != nil { return err } + + var auxNumber string + if err = json.Unmarshal(aux.Number, &auxNumber); err != nil { + auxNumber = string(aux.Number) + } + number := apd.Decimal{} - if _, _, err := number.SetString(aux.Number); err != nil { - return InvalidNumberError{aux.Number} + if _, _, err := number.SetString(auxNumber); err != nil { + return InvalidNumberError{auxNumber} } if aux.CurrencyCode == "" || !IsValid(aux.CurrencyCode) { return InvalidCurrencyCodeError{aux.CurrencyCode} diff --git a/amount_test.go b/amount_test.go index 8c7db03..7859037 100644 --- a/amount_test.go +++ b/amount_test.go @@ -812,6 +812,32 @@ func TestAmount_UnmarshalJSON(t *testing.T) { t.Errorf("got %T, want currency.InvalidNumberError", err) } + d = []byte(`{"number": {"key": "value"}, "currency": "USD"}`) + err = json.Unmarshal(d, unmarshalled) + if e, ok := err.(currency.InvalidNumberError); ok { + if e.Number != `{"key": "value"}` { + t.Errorf(`got %v, "want {"key": "value"}"`, e.Number) + } + wantError := `invalid number "{\"key\": \"value\"}"` + if e.Error() != wantError { + t.Errorf("got %v, want %v", e.Error(), wantError) + } + } else { + t.Errorf("got %T, want currency.InvalidNumberError", err) + } + + d = []byte(`{"number":3.45,"currency":"USD"}`) + err = json.Unmarshal(d, unmarshalled) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if unmarshalled.Number() != "3.45" { + t.Errorf("got %v, want 3.45", unmarshalled.Number()) + } + if unmarshalled.CurrencyCode() != "USD" { + t.Errorf("got %v, want USD", unmarshalled.CurrencyCode()) + } + d = []byte(`{"number":"3.45","currency":"usd"}`) err = json.Unmarshal(d, unmarshalled) if e, ok := err.(currency.InvalidCurrencyCodeError); ok {