SPR-7210 Add setModelKey and setModelKeys to MappingJacksonJsonView for consistency with MarshallingView.

This commit is contained in:
Rossen Stoyanchev 2011-06-22 19:08:44 +00:00
parent 6fa451733e
commit 5797fe7f62
2 changed files with 49 additions and 16 deletions

View File

@ -16,9 +16,11 @@
package org.springframework.web.servlet.view.json; package org.springframework.web.servlet.view.json;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -26,7 +28,6 @@ import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializerFactory; import org.codehaus.jackson.map.SerializerFactory;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
@ -38,8 +39,9 @@ import org.springframework.web.servlet.view.AbstractView;
* href="http://jackson.codehaus.org/">Jackson's</a> {@link ObjectMapper}. * href="http://jackson.codehaus.org/">Jackson's</a> {@link ObjectMapper}.
* *
* <p>By default, the entire contents of the model map (with the exception of framework-specific classes) will be * <p>By default, the entire contents of the model map (with the exception of framework-specific classes) will be
* encoded as JSON. For cases where the contents of the map need to be filtered, users may specify a specific set of * encoded as JSON. If the model contains only one key, you can have it extracted encoded as JSON alone via
* model attributes to encode via the {@link #setRenderedAttributes(Set) renderedAttributes} property. * {@link #setExtractValueFromSingleKeyModel(boolean)}. Or you can select specific model attributes to be encoded
* as JSON via ... TODO
* *
* @author Jeremy Grelle * @author Jeremy Grelle
* @author Arjen Poutsma * @author Arjen Poutsma
@ -60,7 +62,7 @@ public class MappingJacksonJsonView extends AbstractView {
private boolean prefixJson = false; private boolean prefixJson = false;
private Set<String> renderedAttributes; private Set<String> modelKeys;
private boolean extractValueFromSingleKeyModel = false; private boolean extractValueFromSingleKeyModel = false;
@ -96,7 +98,7 @@ public class MappingJacksonJsonView extends AbstractView {
} }
/** /**
* Indicates whether the JSON output by this view should be prefixed with "{@code {} &&}". Default is false. * Indicates whether the JSON output by this view should be prefixed with <tt>"{} && "</tt>. Default is false.
* *
* <p> Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. The prefix renders the string * <p> Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. The prefix renders the string
* syntactically invalid as a script so that it cannot be hijacked. This prefix does not affect the evaluation of JSON, * syntactically invalid as a script so that it cannot be hijacked. This prefix does not affect the evaluation of JSON,
@ -105,20 +107,45 @@ public class MappingJacksonJsonView extends AbstractView {
public void setPrefixJson(boolean prefixJson) { public void setPrefixJson(boolean prefixJson) {
this.prefixJson = prefixJson; this.prefixJson = prefixJson;
} }
/**
* Sets the attribute in the model that should be rendered by this view.
* When set, all other model attributes will be ignored.
*/
public void setModelKey(String modelKey) {
this.modelKeys = Collections.singleton(modelKey);
}
/**
* Sets the attributes in the model that should be rendered by this view.
* When set, all other model attributes will be ignored.
*/
public void setModelKeys(Set<String> modelKeys) {
this.modelKeys = modelKeys;
}
/** /**
* Returns the attributes in the model that should be rendered by this view. * Returns the attributes in the model that should be rendered by this view.
*/ */
public Set<String> getRenderedAttributes() { public Set<String> getModelKeys() {
return renderedAttributes; return modelKeys;
} }
/** /**
* Sets the attributes in the model that should be rendered by this view. When set, all other model attributes will be * Sets the attributes in the model that should be rendered by this view.
* ignored. * When set, all other model attributes will be ignored.
* @deprecated use {@link #setModelKeys(Set)} instead
*/ */
public void setRenderedAttributes(Set<String> renderedAttributes) { public void setRenderedAttributes(Set<String> renderedAttributes) {
this.renderedAttributes = renderedAttributes; this.modelKeys = renderedAttributes;
}
/**
* Returns the attributes in the model that should be rendered by this view.
* @deprecated use {@link #getModelKeys()} instead
*/
public Set<String> getRenderedAttributes() {
return modelKeys;
} }
/** /**
@ -180,7 +207,7 @@ public class MappingJacksonJsonView extends AbstractView {
protected Object filterModel(Map<String, Object> model) { protected Object filterModel(Map<String, Object> model) {
Map<String, Object> result = new HashMap<String, Object>(model.size()); Map<String, Object> result = new HashMap<String, Object>(model.size());
Set<String> renderedAttributes = Set<String> renderedAttributes =
!CollectionUtils.isEmpty(this.renderedAttributes) ? this.renderedAttributes : model.keySet(); !CollectionUtils.isEmpty(this.modelKeys) ? this.modelKeys : model.keySet();
for (Map.Entry<String, Object> entry : model.entrySet()) { for (Map.Entry<String, Object> entry : model.entrySet()) {
if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) { if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) {
result.put(entry.getKey(), entry.getValue()); result.put(entry.getKey(), entry.getValue());

View File

@ -16,6 +16,13 @@
package org.springframework.web.servlet.view.json; package org.springframework.web.servlet.view.json;
import static org.easymock.EasyMock.createMock;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@ -31,14 +38,11 @@ import org.codehaus.jackson.map.SerializerFactory;
import org.codehaus.jackson.map.SerializerProvider; import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.annotate.JsonSerialize; import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.ser.BeanSerializerFactory; import org.codehaus.jackson.map.ser.BeanSerializerFactory;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.ScriptableObject;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
@ -153,7 +157,8 @@ public class MappingJacksonJsonViewTest {
public void renderWithCustomSerializerLocatedByFactory() throws Exception { public void renderWithCustomSerializerLocatedByFactory() throws Exception {
SerializerFactory factory = new DelegatingSerializerFactory(); SerializerFactory factory = new DelegatingSerializerFactory();
ObjectMapper mapper = new ObjectMapper(factory); ObjectMapper mapper = new ObjectMapper();
mapper.setSerializerFactory(factory);
view.setObjectMapper(mapper); view.setObjectMapper(mapper);
Object bean = new TestBeanSimple(); Object bean = new TestBeanSimple();
@ -178,7 +183,7 @@ public class MappingJacksonJsonViewTest {
attrs.add("baz"); attrs.add("baz");
attrs.add("nil"); attrs.add("nil");
view.setRenderedAttributes(attrs); view.setModelKeys(attrs);
Map<String, Object> model = new HashMap<String, Object>(); Map<String, Object> model = new HashMap<String, Object>();
model.put("foo", "foo"); model.put("foo", "foo");
model.put("bar", "bar"); model.put("bar", "bar");
@ -207,6 +212,7 @@ public class MappingJacksonJsonViewTest {
assertSame(bean, actual); assertSame(bean, actual);
} }
@SuppressWarnings("rawtypes")
@Test @Test
public void filterTwoKeyModel() throws Exception { public void filterTwoKeyModel() throws Exception {
view.setExtractValueFromSingleKeyModel(true); view.setExtractValueFromSingleKeyModel(true);