0

I want to send two different json response for the same API based on a flag.

I have a final response json as below for /api/v1/student/, which is created by fetching responses from few other REST apis.

{
    "students": [{
        "name": "string",

        "courses": [{
            "courseid": "string",
            "coursename": "string"
        }],
        "studentId": "string",
        "enrollments": [{
            "key1": "string",
            "key2": "string",
            "key3": "string",

            "curricular": [{
                "date": "string",
                "item1": "string",
                "item2": "string",
                "fees": "string",
                "details": [{
                    "item1": "string",
                    "item2": "string"
                }]

            }]
        }]
    }]
}

Consider a scenario where I have to support this response and another similar response where the "details" block will change based on a flag.

Is creating two versions of api as /api/v1/student/ and /api/v2/student/ the only solution or there is other better approach(es)?

A follow up question for going with v2 approach: I am structuring the response as these model objects - Details, Curricular, Enrollment, Students

ex:

Students : {
 Enrollment : {
    Curricular: {
        Details
    }
 }
}

and now since the nested block - Details is changing I will have to repeat all model classes and mark them as V2 and also duplicate the code for mapping the fields. Does that look right? Thanks for your help!

2 Answers 2

0

Is creating two versions of api as /api/v1/student/ and /api/v2/student/ the only solution or there is other better approach(es)?

There're, at least, 2 more I would consider cleaner than 2 different URIs or a query parameter

  • Custom Request headers : Accepted-Version: v1
  • Custom MIME Types : Accept: application/vnd.mydomain.student+json; version=1

There're others, like different DNS

  • V1 : myapi-v1.mydomain.com/api/students
  • V2 : myapi-v2.mydomain.com/api/students

But as you may guess, the common one is versioning the URI (/api/v1/students).

Details is changing I will have to repeat all model classes and mark them as V2 and also duplicate the code for mapping the fields. Does that look right?

It doesn't, but I dare say it's convenient. Since both models are different, it's likely both will evolve and change at different rates and for different reasons, so you don't want any "link" between the two models that prevent you from that.

Maybe you find some classes and mappers you can reuse for both models and that's fine. However, if at some point one model forces you to change these components, don't do it. Instead, do implement concrete classes for the model that required it.

"The thing" classes are quite baffling, better separate the wheat from the chaff.

Finally, bear in mind that DRY is irrelevant when it comes to mappers and plain data objects. It's annoying, but as I said, it's also convenient.

2
  • Thanks, you touched all my concerns and thanks for pointing out irrelevancy of DRY that repetition was bothering me and making me think I am doing something horribly wrong. Different DNS is not an option for me for now. If I go with creating a new response model, then I think I will not be able to use custom header or query params as the return types are different. (Also note, I am using open api for this to define the APIs). I will mostly go ahead with two different api versions that seems to be the most convenient.
    – linoox
    Jul 1, 2021 at 15:47
  • To me, custom mime types is the way to go. Always. The other two are walkarounds.
    – Laiv
    Jul 1, 2021 at 15:52
0

API versions should only be incremented when you change the API in a non-backward compatible way, and expect to switch clients from the old to the new version over a limited timespan, during which you need to support both APIs. If you find a way to include additional information in a newer version of the service without breaking your existing API (for example, adding new fields which are simply ignored by old clients, or adding new endpoints that provide additional functionality to new clients without breaking old clients) that might be preferrable.

If your actual use case requires supporting variants of the API result concurrently to the same clients depending on what they want to present to the user, it is better handled using some way of negotiating what the client expects in the current request. This can be done in request headers, although that might become a bit tricky and is typically done to specify different representations (JSON,XML,...) of the same resource, not for specifying different detail. A simpler option is to just add a query parameter to the URL. For example, your endpoint might look like /api/v1/student/...?details_format=format_1 to select a specific .

1
  • yes here it wont be backward compatible and I am using open api specs to define api. Since I am inclined to build a new response model, I will have two different return types and so query parameter will not help as I cannot have different return type based on query param. Thanks though, it might be a solution for other similar problem.
    – linoox
    Jul 1, 2021 at 15:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.