SPR-6932 Add option to extract value from single-key models in MappingJacksonJsonView
This commit is contained in:
@@ -43,6 +43,7 @@ import org.springframework.web.servlet.view.AbstractView;
|
|||||||
*
|
*
|
||||||
* @author Jeremy Grelle
|
* @author Jeremy Grelle
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
* @see org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
|
* @see org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
@@ -61,8 +62,10 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||||||
|
|
||||||
private Set<String> renderedAttributes;
|
private Set<String> renderedAttributes;
|
||||||
|
|
||||||
private boolean disableCaching = true;
|
private boolean extractValueFromSingleKeyModel = false;
|
||||||
|
|
||||||
|
private boolean disableCaching = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new {@code JacksonJsonView}, setting the content type to {@code application/json}.
|
* Construct a new {@code JacksonJsonView}, setting the content type to {@code application/json}.
|
||||||
*/
|
*/
|
||||||
@@ -127,6 +130,19 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||||||
this.disableCaching = disableCaching;
|
this.disableCaching = disableCaching;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether to serialize models containing a single attribute as a map or whether to
|
||||||
|
* extract the single value from the model and serialize it directly.
|
||||||
|
* The effect of setting this flag is similar to using
|
||||||
|
* {@code MappingJacksonHttpMessageConverter} with an {@code @ResponseBody}.
|
||||||
|
* request-handling method.
|
||||||
|
*
|
||||||
|
* <p>Default is {@code false}.
|
||||||
|
*/
|
||||||
|
public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyModel) {
|
||||||
|
this.extractValueFromSingleKeyModel = extractValueFromSingleKeyModel;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {
|
protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {
|
||||||
response.setContentType(getContentType());
|
response.setContentType(getContentType());
|
||||||
@@ -170,7 +186,7 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||||||
result.put(entry.getKey(), entry.getValue());
|
result.put(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return (this.extractValueFromSingleKeyModel && result.size() == 1) ? result.values().iterator().next() : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,6 +194,36 @@ public class MappingJacksonJsonViewTest {
|
|||||||
validateResult();
|
validateResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void filterSingleKeyModel() throws Exception {
|
||||||
|
view.setExtractValueFromSingleKeyModel(true);
|
||||||
|
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
|
TestBeanSimple bean = new TestBeanSimple();
|
||||||
|
model.put("foo", bean);
|
||||||
|
|
||||||
|
Object actual = view.filterModel(model);
|
||||||
|
|
||||||
|
assertSame(bean, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void filterTwoKeyModel() throws Exception {
|
||||||
|
view.setExtractValueFromSingleKeyModel(true);
|
||||||
|
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
|
TestBeanSimple bean1 = new TestBeanSimple();
|
||||||
|
TestBeanSimple bean2 = new TestBeanSimple();
|
||||||
|
model.put("foo1", bean1);
|
||||||
|
model.put("foo2", bean2);
|
||||||
|
|
||||||
|
Object actual = view.filterModel(model);
|
||||||
|
|
||||||
|
assertTrue(actual instanceof Map);
|
||||||
|
assertSame(bean1, ((Map) actual).get("foo1"));
|
||||||
|
assertSame(bean2, ((Map) actual).get("foo2"));
|
||||||
|
}
|
||||||
|
|
||||||
private void validateResult() throws Exception {
|
private void validateResult() throws Exception {
|
||||||
Object jsResult =
|
Object jsResult =
|
||||||
jsContext.evaluateString(jsScope, "(" + response.getContentAsString() + ")", "JSON Stream", 1, null);
|
jsContext.evaluateString(jsScope, "(" + response.getContentAsString() + ")", "JSON Stream", 1, null);
|
||||||
|
|||||||
@@ -2610,7 +2610,9 @@ simpleReport.reportDataKey=myBeanData</programlisting>
|
|||||||
of framework-specific classes) will be encoded as JSON. For cases where the
|
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
|
contents of the map need to be filtered, users may specify a specific set of
|
||||||
model attributes to encode via the <literal>RenderedAttributes</literal>
|
model attributes to encode via the <literal>RenderedAttributes</literal>
|
||||||
property.</para>
|
property. The <literal>extractValueFromSingleKeyModel</literal> property
|
||||||
|
may also be used to have the value in single-key models extracted and
|
||||||
|
serialized directly rather than as a map of model attributes.</para>
|
||||||
|
|
||||||
<para>JSON mapping can be customized as needed through the use of Jackson's provided
|
<para>JSON mapping can be customized as needed through the use of Jackson's provided
|
||||||
annotations. When further control is needed, a custom
|
annotations. When further control is needed, a custom
|
||||||
|
|||||||
Reference in New Issue
Block a user