Search code examples
javaspring-bootrestmicroservices

Why it is better to avoid returning lists in API?


My question is about returning list in APIs. suppose we have an API which returns a list of Rating.

and this is Rating:

public class Rating {

    private Long movieId;
    private Integer rating;
    .
    .
}

and this is a sample of the API's response:

[{"movieId":5870,"rating":5},{"movieId":1234,"rating":3}]

Ok. now I want to have an enhancement in my API and the enhancement is not to a particular object in the list. for example, I want to add a field which indicates who these Ratings belongs to.

but in this tutorial, the Instructor says:

we cannot return the list anymore. we have to convert it into an object.

Why we cannot return a list anymore? we can have an API response like this:

[{"movieId":5870,"rating":5},{"movieId":1234,"rating":3},"John Doe"]

and it is its code:

@GetMapping("-sth-")
    public List<Object> foo() {

        List<Object> finalList = new ArrayList<>();
        finalList.add(new Rating(5870L, 5));
        finalList.add(new Rating(1234L, 3));
        finalList.add("John Doe");

        return finalList;
    }

then why we don't do that? why he said we cannot return a list anymore? What is the problem in this new version of the API? is it because we are returning a list of Object?


Solution

  • Tl;dr: it's good practice.

    If you think of the API as a contract, I give you this information and you give me that information back, once you return a List<Object> you no longer have any way to reason about what is in that list and what you're supposed to do with it.

    In the absence of "John Doe" in that list, you can tell a JSON parser to turn your response into a List<Rating> and it will without further assistance. However, adding "John Doe" stops it from doing so, the best you can hope for is List<Object>. So now you are required to manually figure out where John Doe is in your list, whether he is there in the first place, etc.

    You may need to write a custom parser or ensure that everyone using this API knows that John Doe may (or may not?) appear in last position, (or first, or anywhere in the middle?) Frankly, it's easier on you as the developer to refactor into using a custom Object, so that you can tell your JSON library to parse the response into an Object of type RatedActor:

    public class RatedActor {
        String name;
        List<Rating> ratings;
    }
    

    That's what OO languages are for (amongst other things) - to be able to present a fine-grained data model. Now you, the compiler, and everybody else who may come into contact with your API and/or code knows clearly: The API returns a RatedActor with these properties. There is no 'hidden knowledge' embedded in a secret list. Otherwise you may as well scramble the API response with an Enigma machine and go "hey, figure that one out, API consumers!"