Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Rest Controller Return Specific Fields

Tags:

I've been going through my head the best way to design a JSON API using Spring MVC. As we all know IO is expensive, and thus I don't want to make the client make several API calls to get what they need. However at the same time I don't necessarily want to return the kitchen sink.

As an example I was working on a game API similar to IMDB but for video games instead.

If I returned everything connected to Game it would look something like this.

/api/game/1

{     "id": 1,     "title": "Call of Duty Advanced Warfare",     "release_date": "2014-11-24",     "publishers": [         {             "id": 1,             "name": "Activision"         }     ],     "developers": [         {             "id": 1,             "name": "Sledge Hammer"         }     ],     "platforms": [         {             "id": 1,             "name": "Xbox One",             "manufactorer": "Microsoft",             "release_date": "2013-11-11"         },         {             "id": 2,             "name": "Playstation 4",             "manufactorer": "Sony",             "release_date": "2013-11-18"         },         {             "id": 3,             "name": "Xbox 360",             "manufactorer": "Microsoft",             "release_date": "2005-11-12"         }     ],     "esrbRating": {         "id": 1,         "code": "T",         "name": "Teen",         "description": "Content is generally suitable for ages 13 and up. May contain violence, suggestive themes, crude humor, minimal blood, simulated gambling and/or infrequent use of strong language."     },     "reviews": [         {             "id": 1,             "user_id": 111,             "rating": 4.5,             "description": "This game is awesome"         }     ] } 

However they may not need all this information, but then again they might. Making calls for everything seems like a bad idea from I/O and performance.

I thought about doing it by specifying include parameter in the requests.

Now for example if you did not specify any includes all you would get back is the following.

{     "id": 1,     "title": "Call of Duty Advanced Warfare",     "release_date": "2014-11-24" } 

However it you want all the information your requests would look something like this.

/api/game/1?include=publishers,developers,platforms,reviews,esrbRating 

This way the client has the ability to specify how much information they want. However I'm kind of at a loss the best way to implement this using Spring MVC.

I'm thinking the controller would look something like this.

public @ResponseBody Game getGame(@PathVariable("id") long id,      @RequestParam(value = "include", required = false) String include)) {          // check which include params are present          // then someone do the filtering? } 

I'm not sure how you would optionally serialize the Game object. Is this even possible. What is the best way to approach this in Spring MVC?

FYI, I am using Spring Boot which includes Jackson for serialization.

like image 513
greyfox Avatar asked May 31 '15 14:05

greyfox


2 Answers

Instead of returning a Game object, you could serialize it as as a Map<String, Object>, where the map keys represent the attribute names. So you can add the values to your map based on the include parameter.

@ResponseBody public Map<String, Object> getGame(@PathVariable("id") long id, String include) {      Game game = service.loadGame(id);     // check the `include` parameter and create a map containing only the required attributes     Map<String, Object> gameMap = service.convertGameToMap(game, include);      return gameMap;  } 

As an example, if you have a Map<String, Object> like this:

gameMap.put("id", game.getId()); gameMap.put("title", game.getTitle()); gameMap.put("publishers", game.getPublishers()); 

It would be serialized like this:

{   "id": 1,   "title": "Call of Duty Advanced Warfare",   "publishers": [     {         "id": 1,         "name": "Activision"     }   ] } 
like image 152
Marlon Bernardes Avatar answered Oct 02 '22 15:10

Marlon Bernardes


Being aware that my answer comes quite late: I'd recommend to look at Projections.

What you're asking for is what projections are about.

Since you're asking about Spring I'd give this one a try: https://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts

A very dynamic way for providing different projections on demand is offered by GraphQL. I just came across a very helpful article about how to use GraphQL with SpringBoot: https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/

like image 42
yaccob Avatar answered Oct 02 '22 15:10

yaccob