I'm using spring to create a restful api, so far so good, my question is how to model the fields that go to the response dynamically?
Thats the controller that i'm using:
@Controller
public class AlbumController {
@Autowired
private MusicService musicService;
@RequestMapping(value = "/albums", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Collection<Resource<Album>> getAllAlbums() {
Collection<Album> albums = musicService.getAllAlbums();
List<Resource<Album>> resources = new ArrayList<Resource<Album>>();
for (Album album : albums) {
resources.add(this.getAlbumResource(album));
}
return resources;
}
@RequestMapping(value = "/album/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Resource<Album> getAlbum(@PathVariable(value = "id") String id) {
Album album = musicService.getAlbum(id);
return getAlbumResource(album);
}
private Resource<Album> getAlbumResource(Album album) {
Resource<Album> resource = new Resource<Album>(album);
// Link to Album
resource.add(linkTo(methodOn(AlbumController.class).getAlbum(album.getId())).withSelfRel());
// Link to Artist
resource.add(linkTo(methodOn(ArtistController.class).getArtist(album.getArtist().getId())).withRel("artist"));
// Option to purchase Album
if (album.getStockLevel() > 0) {
resource.add(linkTo(methodOn(AlbumController.class).purchaseAlbum(album.getId())).withRel("album.purchase"));
}
return resource;
}
@RequestMapping(value = "/album/purchase/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Resource<Album> purchaseAlbum(@PathVariable(value = "id") String id) {
Album a = musicService.getAlbum(id);
a.setStockLevel(a.getStockLevel() - 1);
Resource<Album> resource = new Resource<Album>(a);
resource.add(linkTo(methodOn(AlbumController.class).getAlbum(id)).withSelfRel());
return resource;
}
}
And the model:
public class Album {
private final String id;
private final String title;
private final Artist artist;
private int stockLevel;
public Album(final String id, final String title, final Artist artist, int stockLevel) {
this.id = id;
this.title = title;
this.artist = artist;
this.stockLevel = stockLevel;
}
public String getId() {
return id;
}
public String getTitle() {
return title;
}
public Artist getArtist() {
return artist;
}
public int getStockLevel() {
return stockLevel;
}
public void setStockLevel(int stockLevel) {
this.stockLevel = stockLevel;
}
}
var json = { 'name': John Doe, 'nickname': Johnny } var key = "name"; delete json[key];
The Jackson @JsonIgnore annotation can be used to ignore a certain property or field of a Java object. The property can be ignored both when reading JSON into Java objects and when writing Java objects into JSON.
Using the Delete operator The Delete operator is the easiest way to delete the object property. if we want to delete multiple properties which are in the object, we need to use this operator multiple times. In the following example, we have created a JSON Object with keys and values.
How do you remove a key value pair from a JSON object? JsonObject::remove() removes a key-value pair from the object pointed by the JsonObject . If the JsonObject is null, this function does nothing.
I'm struggling with this requirement, too.
The following code is a workaround using the JsonViews already mentioned by @beerbajay in the comment to your question:
http://wiki.fasterxml.com/JacksonJsonViews
I'm using Spring Boot 1.2.3.
package demo;
public class Views {
static interface Public {}
static interface Internal extends Public {}
}
package demo;
import com.fasterxml.jackson.annotation.JsonView;
public class Album {
@JsonView(Views.Public.class)
private String id;
@JsonView(Views.Public.class)
private String title;
@JsonView(Views.Public.class)
private String artist;
@JsonView(Views.Internal.class)
private String secret;
public Album(String id, String title, String artist, String secret) {
this.id = id;
this.title = title;
this.artist = artist;
this.secret = secret;
}
}
package demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
@RestController
public class AlbumController {
@Autowired
ObjectMapper mapper;
@RequestMapping(value = "/album", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public String getAlbum() throws JsonProcessingException {
Album foo = new Album("1", "foo", "John Doe", "secretProperty");
// replace the following value with runtime logic of your choice,
// e.g. role of a user
boolean forInternal = false;
ObjectWriter viewWriter;
if (forInternal) {
viewWriter = mapper.writerWithView(Views.Internal.class);
} else {
viewWriter = mapper.writerWithView(Views.Public.class);
}
return viewWriter.writeValueAsString(foo);
}
}
So the key is to use jackson's ObjectMapper and ObjectWriter to generate a string of the json representation of your object.
Feels kind of ugly to me, but works.
Certainly the question remains how this scales when defining more than one RequestMapping
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With