Skip to content

Commit

Permalink
Create custom unmarshaller for ShippingLines (#71) (#105)
Browse files Browse the repository at this point in the history
* Create custom unmarshaller for ShippingLines

 - Implemented custom unmarshaler to handle requested_fulfillment_service_id
sometimes being returned as json numbers or json nulls instead of json strings.
  • Loading branch information
at-silva authored Jun 4, 2020
1 parent 0398b1e commit e4ee88f
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"id": 254721542,
"code": "INT.TP",
"price": "4.00",
"price_set": {
"shop_money": {
"amount": "4.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "3.17",
"currency_code": "EUR"
}
},
"discounted_price": "4.00",
"discounted_price_set": {
"shop_money": {
"amount": "4.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "3.17",
"currency_code": "EUR"
}
},
"source": "canada_post",
"title": "Small Packet International Air",
"tax_lines": [
{
"price": 13.50,
"rate": 0.06,
"title": "State tax"
},
{
"price": 12.50,
"rate": 0.05,
"title": "Federal tax"
}
],
"carrier_identifier": "third_party_carrier_identifier",
"requested_fulfillment_service_id":
}
42 changes: 42 additions & 0 deletions fixtures/shippinglines/requested_fulfillment_service_id_null.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"id": 254721542,
"code": "INT.TP",
"price": "4.00",
"price_set": {
"shop_money": {
"amount": "4.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "3.17",
"currency_code": "EUR"
}
},
"discounted_price": "4.00",
"discounted_price_set": {
"shop_money": {
"amount": "4.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "3.17",
"currency_code": "EUR"
}
},
"source": "canada_post",
"title": "Small Packet International Air",
"tax_lines": [
{
"price": 13.50,
"rate": 0.06,
"title": "State tax"
},
{
"price": 12.50,
"rate": 0.05,
"title": "Federal tax"
}
],
"carrier_identifier": "third_party_carrier_identifier",
"requested_fulfillment_service_id": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"id": 254721542,
"code": "INT.TP",
"price": "4.00",
"price_set": {
"shop_money": {
"amount": "4.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "3.17",
"currency_code": "EUR"
}
},
"discounted_price": "4.00",
"discounted_price_set": {
"shop_money": {
"amount": "4.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "3.17",
"currency_code": "EUR"
}
},
"source": "canada_post",
"title": "Small Packet International Air",
"tax_lines": [
{
"price": 13.50,
"rate": 0.06,
"title": "State tax"
},
{
"price": 12.50,
"rate": 0.05,
"title": "Federal tax"
}
],
"carrier_identifier": "third_party_carrier_identifier",
"requested_fulfillment_service_id": 123456
}
42 changes: 42 additions & 0 deletions fixtures/shippinglines/valid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"id": 254721542,
"code": "INT.TP",
"price": "4.00",
"price_set": {
"shop_money": {
"amount": "4.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "3.17",
"currency_code": "EUR"
}
},
"discounted_price": "4.00",
"discounted_price_set": {
"shop_money": {
"amount": "4.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "3.17",
"currency_code": "EUR"
}
},
"source": "canada_post",
"title": "Small Packet International Air",
"tax_lines": [
{
"price": 13.50,
"rate": 0.06,
"title": "State tax"
},
{
"price": 12.50,
"rate": 0.05,
"title": "Federal tax"
}
],
"carrier_identifier": "third_party_carrier_identifier",
"requested_fulfillment_service_id": "third_party_fulfillment_service_id"
}
24 changes: 24 additions & 0 deletions order.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,30 @@ type ShippingLines struct {
TaxLines []TaxLine `json:"tax_lines,omitempty"`
}

// UnmarshalJSON custom unmarshaller for ShippingLines implemented to handle requested_fulfillment_service_id being
// returned as json numbers or json nulls instead of json strings
func (sl *ShippingLines) UnmarshalJSON(data []byte) error {
type alias ShippingLines
aux := &struct {
*alias
RequestedFulfillmentServiceID interface{} `json:"requested_fulfillment_service_id"`
}{alias: (*alias)(sl)}

err := json.Unmarshal(data, &aux)
if err != nil {
return err
}

switch aux.RequestedFulfillmentServiceID.(type) {
case nil:
sl.RequestedFulfillmentServiceID = ""
default:
sl.RequestedFulfillmentServiceID = fmt.Sprintf("%v", aux.RequestedFulfillmentServiceID)
}

return nil
}

type TaxLine struct {
Title string `json:"title,omitempty"`
Price *decimal.Decimal `json:"price,omitempty"`
Expand Down
138 changes: 138 additions & 0 deletions order_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,72 @@ func TestLineItemUnmarshalJSONPropertiesObject(t *testing.T) {
testLineItem(t, expected, actual)
}

// TestShippingLines tests unmarshalling ShippingLines.RequestFulfillmentServiceID from a JSON string
func TestShippingLines_UnmarshallJSON(t *testing.T) {
setup()
defer teardown()

actual := ShippingLines{}

err := actual.UnmarshalJSON(loadFixture("shippinglines/valid.json"))
if err != nil {
t.Errorf("ShippingLines.UnmarshalJSON returned error: %v", err)
}

expected := validShippingLines()

testShippingLines(t, expected, actual)
}

// TestShippingLines tests unmarshalling ShippingLines.RequestFulfillmentServiceID from a JSON Number
func TestShippingLines_UnmarshallJSON_RequestFulfillmentServiceIDNumber(t *testing.T) {
setup()
defer teardown()

actual := ShippingLines{}

err := actual.UnmarshalJSON(loadFixture("shippinglines/requested_fulfillment_service_id_number.json"))
if err != nil {
t.Errorf("ShippingLines.UnmarshalJSON returned error: %v", err)
}

expected := validShippingLines()
expected.RequestedFulfillmentServiceID = "123456"

testShippingLines(t, expected, actual)
}

// TestShippingLines tests unmarshalling ShippingLines.RequestFulfillmentServiceID from a JSON null
func TestShippingLines_UnmarshallJSON_RequestFulfillmentServiceIDNull(t *testing.T) {
setup()
defer teardown()

actual := ShippingLines{}

err := actual.UnmarshalJSON(loadFixture("shippinglines/requested_fulfillment_service_id_null.json"))
if err != nil {
t.Errorf("ShippingLines.UnmarshalJSON returned error: %v", err)
}

expected := validShippingLines()
expected.RequestedFulfillmentServiceID = ""

testShippingLines(t, expected, actual)
}

// TestShippingLines tests unmarshalling ShippingLines.RequestFulfillmentServiceID from a malformed JSON
func TestShippingLines_UnmarshallJSON_RequestFulfillmentServiceIDInvalid(t *testing.T) {
setup()
defer teardown()

actual := ShippingLines{}

err := actual.UnmarshalJSON(loadFixture("shippinglines/requested_fulfillment_service_id_invalid.json"))
if err == nil || !strings.Contains(err.Error(), "invalid character '}'") {
t.Errorf("ShippingLines.UnmarshalJSON expected invalid character '}' %v", err)
}
}

func testLineItem(t *testing.T, expected, actual LineItem) {
if actual.ID != expected.ID {
t.Errorf("LineItem.ID should be (%v), was (%v)", expected.ID, actual.ID)
Expand Down Expand Up @@ -964,6 +1030,46 @@ func testTaxLines(t *testing.T, expected, actual []TaxLine) {
}
}

func testShippingLines(t *testing.T, expected, actual ShippingLines) {
if actual.ID != expected.ID {
t.Errorf("ShippingLines.ID should be (%v), was (%v)", expected.ID, actual.ID)
}

if actual.Title != expected.Title {
t.Errorf("ShippingLines.Title should be (%v), was (%v)", expected.Title, actual.Title)
}

if !actual.Price.Equals(*expected.Price) {
t.Errorf("ShippingLines.Price should be (%v), was (%v)", expected.Price, actual.Price)
}

if actual.Code != expected.Code {
t.Errorf("ShippingLines.Code should be (%v), was (%v)", expected.Code, actual.Code)
}

if actual.Source != expected.Source {
t.Errorf("ShippingLines.Source should be (%v), was (%v)", expected.Source, actual.Source)
}

if actual.Phone != expected.Phone {
t.Errorf("ShippingLines.Phone should be (%v), was (%v)", expected.Phone, actual.Phone)
}

if actual.RequestedFulfillmentServiceID != expected.RequestedFulfillmentServiceID {
t.Errorf("ShippingLines.RequestedFulfillmentServiceID should be (%v), was (%v)", expected.RequestedFulfillmentServiceID, actual.RequestedFulfillmentServiceID)
}

if actual.DeliveryCategory != expected.DeliveryCategory {
t.Errorf("ShippingLines.DeliveryCategory should be (%v), was (%v)", expected.DeliveryCategory, actual.DeliveryCategory)
}

if actual.CarrierIdentifier != expected.CarrierIdentifier {
t.Errorf("ShippingLines.CarrierIdentifier should be (%v), was (%v)", expected.CarrierIdentifier, actual.CarrierIdentifier)
}

testTaxLines(t, expected.TaxLines, actual.TaxLines)
}

func propertiesEmptyStructLientItem() LineItem {
return LineItem{
Properties: []NoteAttribute{},
Expand Down Expand Up @@ -1078,3 +1184,35 @@ func validLineItem() LineItem {
},
}
}

func validShippingLines() ShippingLines {
price := decimal.New(400, -2)
tl1Price := decimal.New(1350, -2)
tl1Rate := decimal.New(6, -2)
tl2Price := decimal.New(1250, -2)
tl2Rate := decimal.New(5, -2)

return ShippingLines{
ID: int64(254721542),
Title: "Small Packet International Air",
Price: &price,
Code: "INT.TP",
Source: "canada_post",
Phone: "",
RequestedFulfillmentServiceID: "third_party_fulfillment_service_id",
DeliveryCategory: "",
CarrierIdentifier: "third_party_carrier_identifier",
TaxLines: []TaxLine{
{
Title: "State tax",
Price: &tl1Price,
Rate: &tl1Rate,
},
{
Title: "Federal tax",
Price: &tl2Price,
Rate: &tl2Rate,
},
},
}
}

0 comments on commit e4ee88f

Please sign in to comment.