DATAREST-117 - Added support to detect @JsonIgnore and @JsonIgnoreProperties.

Wrote test cases to verify it handles class level and attribute level annotations to ignore properties when rendering PersistentEntityResources.

Original pull request: #135.
This commit is contained in:
Greg Turnquist
2014-02-14 09:49:38 -06:00
committed by Oliver Gierke
parent b3b091e309
commit 171ab2583e
4 changed files with 101 additions and 5 deletions

View File

@@ -16,6 +16,8 @@
package org.springframework.data.rest.webmvc.json;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -44,6 +46,7 @@ import org.springframework.util.Assert;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.Version;
@@ -133,6 +136,17 @@ public class PersistentEntityJackson2Module extends SimpleModule {
final Map<String, Object> model = new LinkedHashMap<String, Object>();
String[] fieldsToIgnore = new String[]{};
for (Annotation annotation : entity.getType().getAnnotations()) {
if (annotation.annotationType().equals(JsonIgnoreProperties.class)) {
JsonIgnoreProperties ann = (JsonIgnoreProperties)annotation;
fieldsToIgnore = ann.value();
break;
}
}
final String[] finalFieldsToIgnore = fieldsToIgnore;
try {
entity.doWithProperties(new SimplePropertyHandler() {
@@ -151,6 +165,24 @@ public class PersistentEntityJackson2Module extends SimpleModule {
return;
}
final Method getter = property.getGetter();
if (getter != null) {
final Annotation[] annotations = getter.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation.annotationType().equals(JsonIgnore.class)) {
if (((JsonIgnore)annotation).value()) {
return;
}
}
}
}
for (String fieldToIgnore : finalFieldsToIgnore) {
if (property.getName().equals(fieldToIgnore)) {
return;
}
}
// Property is a normal or non-managed property.
model.put(property.getName(), wrapper.getProperty(property));
}

View File

@@ -262,7 +262,16 @@ public abstract class AbstractWebIntegrationTests {
return (T) jsonPathResult;
}
protected String assertJsonPathEquals(String path, MockHttpServletResponse response, String expected)
protected void assertJsonPathDoesntExist(String path, MockHttpServletResponse response) throws Exception {
try {
JsonPath.read(response.getContentAsString(), path);
fail(path + " should have failed");
} catch (InvalidPathException e) {
}
}
protected String assertJsonPathEquals(String path, String expected, MockHttpServletResponse response)
throws Exception {
String jsonQueryResults = assertHasJsonPathValue(path, response);

View File

@@ -176,6 +176,29 @@ public class JpaWebTests extends AbstractWebIntegrationTests {
).andExpect(status().isCreated());
}
/**
* @see DATAREST-117
*/
@Test
public void createPersonThenVerifyIgnoredAttributesDontExist() throws Exception {
Link peopleLink = discoverUnique("people");
ObjectMapper mapper = new ObjectMapper();
Person frodo = new Person("Frodo", "Baggins");
frodo.setAge(77);
frodo.setHeight(42);
frodo.setWeight(75);
String frodoString = mapper.writeValueAsString(frodo);
MockHttpServletResponse response = postAndGet(peopleLink, frodoString, MediaType.APPLICATION_JSON);
assertJsonPathEquals("$.firstName", "Frodo", response);
assertJsonPathEquals("$.lastName", "Baggins", response);
assertJsonPathDoesntExist("$.age", response);
assertJsonPathDoesntExist("$.height", response);
assertJsonPathDoesntExist("$.weight", response);
}
/**
* @see DATAREST-95
*/
@@ -354,14 +377,14 @@ public class JpaWebTests extends AbstractWebIntegrationTests {
MockHttpServletResponse createdPerson = postAndGet(peopleLink, frodoString, MediaType.APPLICATION_JSON);
Link frodoLink = assertHasLinkWithRel("self", createdPerson);
assertJsonPathEquals("$.firstName", createdPerson, "Frodo");
assertJsonPathEquals("$.firstName", "Frodo", createdPerson);
String bilboWithFrodosLinks = createdPerson.getContentAsString().replace("Frodo", "Bilbo");
MockHttpServletResponse overwrittenResponse = putAndGet(frodoLink, bilboWithFrodosLinks, MediaType.APPLICATION_JSON);
assertHasLinkWithRel("self", overwrittenResponse);
assertJsonPathEquals("$.firstName", overwrittenResponse, "Bilbo");
assertJsonPathEquals("$.firstName", "Bilbo", overwrittenResponse);
}
private List<Link> preparePersonResources(Person primary, Person... persons) throws Exception {

View File

@@ -14,14 +14,19 @@ import javax.persistence.ManyToOne;
import javax.persistence.PrePersist;
import javax.validation.constraints.NotNull;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonIgnoreType;
import org.springframework.data.rest.core.annotation.Description;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* An entity that represents a person.
*
*
* @author Jon Brisbin
*/
@Entity
@JsonIgnoreProperties({"height", "weight"})
public class Person {
private Long id;
@@ -30,6 +35,9 @@ public class Person {
@Description("A person's siblings") private List<Person> siblings = Collections.emptyList();
private Person father;
@Description("Timestamp this person object was created") private Date created;
private int age;
private int height;
private int weight;
public Person() {}
@@ -102,4 +110,28 @@ public class Person {
this.created = Calendar.getInstance().getTime();
}
}
@JsonIgnore
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}