'REST API same url - different response type

We are in process of designing a public exposed REST API. Trying to conform to industry standards (https://restfulapi.net/) we came up to the following design questions:

  • one of the APIs is in the following format HTTP://www.mycompany.com/api/v1/items which returns DTO translated to JSON like this
[
    { id: 1, code: 'I1' },
    { id: 2, code: 'I2' }, 
    { id: 3, code: 'I3' }
]

Along with this API, we got a requirement to support richer DTO as follows

[
    { id: 1, code: 'I1', name: 'Item1', Description: 'This is item1' }, 
    { id: 2, code: 'I2', name: 'Item2', Description: 'This is item2' }, 
    { id: 3, code: 'I3', name: 'Item3', Description: 'This is item3' }
]

How would you shape URL format (http:/.../..) richer response which has to be side-by-side with the simpler existing one? Basically, we would like to have something like HTTP://www.mycompany.com/api/v1/items which is user-friendly format, stick to the standard, but again support multiple response formats. Keep in mind that we are hierarchically at the same level. Resource-naming is nicely explained here.

The forward-slash (/) character is used in the path portion of the URI to indicate a hierarchical relationship between resources. e.g.
http://api.example.com/device-management
http://api.example.com/device-management/managed-devices
http://api.example.com/device-management/managed-devices/{id}
http://api.example.com/device-management/managed-devices/{id}/scripts
http://api.example.com/device-management/managed-devices/{id}/scripts/{id}

  • to support versioning how to ensure at a deeper level backward compatibility. Our code is written in Java or C# and it's consumed by internal applications and API we are developing. Right now our API has published v1 which is driven by ItemService (version alpha). Dev team is developing ItemService (version beta) which is an enriched version of the former one. Should I approach with Open-Close SOLID principle? Any other pattern?
//version 1  - alpha
class ItemService {  
    public void OrderItem(Item item)
    {
        if(item.ItemId == -1) //Create if doesn't exist
        {
            CreateItem();
        }
    }
}


//version 2 - beta
class ItemService {
    public void OrderItem(Item item)
    {
        if(item.ItemId == -1) //Create if doesn't exist
        {
            CreateItem();
        } 
        //Update if exist
        else 
        {
            UpdateItem(item);
            SendEmail();
        }     
    }
}```

Bottom line, our goal is to cover multiple API versions (alpha, beta...) fully supported with a backend that is also written in version-driven manner.
 





Solution 1:[1]

For your first problem I would see the richer DTO as the default that is returned for the regular URLs. Then add a query parameter to filter for the fields you want, if you need to strip out some of the fields. (Like http://www.example.com/api/v1/items?fields=id,code)

If the query parameter is left out, the richer DTOs are fetched. If the default has to be the slim DTO it is also possible, but not as elegant or expandable.

For the second problem I would recommend to develop each version of the API as individual deployable artifact. Then deploy it with the version number as context (piece of the path somewhere at the beginning). This way you can fix bugs in older versions, undeploy older versions on demand individually without touching the other versions, and also add new versions without any hassle.

As REST interfaces should be stateless, these multiple versions in multiple deployables should not cause any extra problems.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 cyberbrain