0

We have a case where we have a rest endpoint and the response will be different depending on the application flow. The properties inside the json will differ, so the question is whether we want a response containing a json that will have different structure depending on application flow.

We basically have three options as I see it now. Either we could have two properties and one of them will always be null (customer or businessCustomer):

{
  "data": {
    "target": "Business",
    "customer": null,
    "businessCustomer": {
        ....
    }
}

{
  "data": {
    "target": "Customer",
    "customer": {
        ....
    },
    "businessCustomer": null,
}

Or we will have only one property where the the contents of that json object will differ (customer always populated):

{
  "data": {
    "target": "Customer or business",
    "customer": {
        ....
    }
}

I'm thinking it might be hard to consume the data with only one property. How would you serialize that in a smooth way in strongly typed langauges...

Which way is best? Thanks in advance!

Jim Aho
  • 9,932
  • 15
  • 56
  • 87
  • Are `customer` and `businessCustomer` two separate entities? – Tom Jun 07 '17 at 10:57
  • 2
    Create new call for different types of request. Don't mix up your data types. Keep them separate because they are different. If you mix it up then what next? Are you going to keep mixing up when you have different types of calls to implement? – Ross Miller Jun 07 '17 at 10:57
  • I don't think your REST API should be altering its response based on what the consumer is doing - it should be agnostic. – Tom Jun 07 '17 at 10:59
  • If your Customer and BusinessCustomer entities are similar and can derive from a base class then maybe https://stackoverflow.com/questions/6348215/how-to-deserialize-json-into-ienumerablebasetype-with-newtonsoft-json-net will help? – swatsonpicken Jun 07 '17 at 11:05
  • Yes I would say so, but technically they could share a base class @Tom – Jim Aho Jun 07 '17 at 11:20
  • I only showed part of the entire response, most information in the response is the same no matter if its a customer or businessCustomer. @RossMiller . Creating a new endpoint is not something we want to do here. The part that integrates with us shall have only single endpoint to call, now we just need to structure the response in a good way. – Jim Aho Jun 07 '17 at 11:22
  • Ok. The json could contain the type of data object. Even if it's the same data for the most part. So if you included the name of your class within the data, you could use reflection to deserialise into a strongly typed class since you know the data type. That way there will be only one call which can serailise into different strong types. – Ross Miller Jun 07 '17 at 11:26

2 Answers2

1

We faced similar scenario in our development and solved it using the resource type and created a base class for all it's sub-types. It is a generic implementation and the client side code is responsible for checking the @type and creating respective object from their side.

CustomerResource (Considering this as Base Class)
    BusinessCustomerResource (Extended from Customer Resource)

For Business Customer Resource:

{
    "someOtherElement": "value",
    "customer" : {
                    "@type" : "BusinessCustomerResource",
                    "faxNumber" : "35635636",
                    "email" : "test@gmail.com",
                    "phone" : "2503334444",
                    "contactName" : "name",
                    "firstName" : "Owner",
                    "lastName" : "lastName"
                    ...
                    "address" : {
                      "@type" : "InternationalAddressResource",
                      "province" : "AB",
                      "country" : "Canada",
                      ...
                    }
                }
}

For Customer Resource:

{
    "someOtherElement": "value",
    "customer" : {
                    "@type" : "CustomerResource",
                    "email" : "test@gmail.com",
                    "phone" : "2503334444",
                    "firstName" : "Owner",
                    "lastName" : "lastName"
                    ...
                    "address" : {
                      "@type" : "PostalAddressResource",
                      "province" : "AB",
                      "country" : "Canada",
                      ...
                    }
                }
}
Lijin
  • 225
  • 2
  • 15
  • Yes, this seem to be one way to go. However currently we don't have a shared baseclass and i'm not fond of passing the @type property... – Jim Aho Jun 08 '17 at 07:39
-1

I would suggest to have common response format. You can observe similar example in real world (Example : HTTP Request/Response).

You can standardise it like below:

{
  "statusCode": 0,
  "statusDesc": "Response description",
  "value": null
}

Here statusCode and statusDesc would be common across all your response and value would change depending on the api (In your case u can pass customer or businessCustomer respectively). By doing so, Client can use common utility to understand if it is success/failure and take respective action.

  • The response format is already "common". 80% of the properties (which are now shown in my example) is the same across all responses. I interpret your suggestion as that you recommend one property instead of two to seperate the customer entities. – Jim Aho Jun 08 '17 at 07:37