/** * Set the {@code ObjectMapper} for this view. * If not set, a default {@link ObjectMapper#ObjectMapper() ObjectMapper} will be used. * <p>Setting a custom-configured {@code ObjectMapper} is one way to take further control of * the JSON serialization process. The other option is to use Jackson's provided annotations * on the types to be serialized, in which case a custom-configured ObjectMapper is unnecessary. */ public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; configurePrettyPrint(); }
protected AbstractJackson2View(ObjectMapper objectMapper, String contentType) { this.objectMapper = objectMapper; configurePrettyPrint(); setContentType(contentType); setExposePathVariables(false); }
@Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { ByteArrayOutputStream temporaryStream = null; OutputStream stream; if (this.updateContentLength) { temporaryStream = createTemporaryOutputStream(); stream = temporaryStream; } else { stream = response.getOutputStream(); } Object value = filterAndWrapModel(model, request); writeContent(stream, value); if (temporaryStream != null) { writeToResponse(response, temporaryStream); } }
@Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.enableContentNegotiation(new MappingJackson2JsonView()); registry.jsp("/", ".jsp"); }
@Test public void renderWithCustomSerializerLocatedByFactory() throws Exception { SerializerFactory factory = new DelegatingSerializerFactory(null); ObjectMapper mapper = new ObjectMapper(); mapper.setSerializerFactory(factory); view.setObjectMapper(mapper); Object bean = new TestBeanSimple(); Map<String, Object> model = new HashMap<>(); model.put("foo", bean); model.put("bar", new TestChildBean()); view.render(model, request, response); String result = response.getContentAsString(); assertTrue(result.length() > 0); assertTrue(result.contains("\"foo\":{\"testBeanSimple\":\"custom\"}")); validateResult(); }
@Test public void filterSingleKeyModel() throws Exception { view.setExtractValueFromSingleKeyModel(true); Map<String, Object> model = new HashMap<>(); TestBeanSimple bean = new TestBeanSimple(); model.put("foo", bean); Object actual = view.filterModel(model); assertSame(bean, actual); }
@Test public void renderWithPrettyPrint() throws Exception { ModelMap model = new ModelMap("foo", new TestBeanSimple()); view.setPrettyPrint(true); view.render(model, request, response); String result = response.getContentAsString().replace("\r\n", "\n"); assertTrue("Pretty printing not applied:\n" + result, result.startsWith("{\n \"foo\" : {\n ")); validateResult(); }
@Test public void renderSimpleBean() throws Exception { Object bean = new TestBeanSimple(); Map<String, Object> model = new HashMap<>(); model.put("bindingResult", mock(BindingResult.class, "binding_result")); model.put("foo", bean); view.setUpdateContentLength(true); view.render(model, request, response); assertTrue(response.getContentAsString().length() > 0); assertEquals(response.getContentAsString().length(), response.getContentLength()); validateResult(); }
@Override protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) { setResponseContentType(request, response); response.setCharacterEncoding(this.encoding.getJavaName()); if (this.disableCaching) { response.addHeader("Cache-Control", "no-store"); } }
@Test public void renderWithCustomSerializerLocatedByAnnotation() throws Exception { Object bean = new TestBeanSimpleAnnotated(); Map<String, Object> model = new HashMap<>(); model.put("foo", bean); view.render(model, request, response); assertTrue(response.getContentAsString().length() > 0); assertEquals("{\"foo\":{\"testBeanSimple\":\"custom\"}}", response.getContentAsString()); validateResult(); }
@Test public void renderSimpleBeanNotPrefixed() throws Exception { view.setPrefixJson(false); renderSimpleBean(); assertFalse(response.getContentAsString().startsWith(")]}', ")); }
@Test public void renderSimpleMapPrefixed() throws Exception { view.setPrefixJson(true); renderSimpleMap(); }
@Override public JsonSerializer<Object> createSerializer(SerializerProvider prov, JavaType type) throws JsonMappingException { if (type.getRawClass() == TestBeanSimple.class) { return new TestBeanSimpleSerializer(); } else { return super.createSerializer(prov, type); } } }
@Test public void isExposePathVars() { assertEquals("Must not expose path variables", false, view.isExposePathVariables()); }
protected AbstractJackson2View(ObjectMapper objectMapper, String contentType) { this.objectMapper = objectMapper; configurePrettyPrint(); setContentType(contentType); setExposePathVariables(false); }
@SuppressWarnings("rawtypes") @Test public void filterTwoKeyModel() throws Exception { view.setExtractValueFromSingleKeyModel(true); Map<String, Object> model = new HashMap<>(); 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")); }
/** * Whether to use the default pretty printer when writing the output. * This is a shortcut for setting up an {@code ObjectMapper} as follows: * <pre class="code"> * ObjectMapper mapper = new ObjectMapper(); * mapper.configure(SerializationFeature.INDENT_OUTPUT, true); * </pre> * <p>The default value is {@code false}. */ public void setPrettyPrint(boolean prettyPrint) { this.prettyPrint = prettyPrint; configurePrettyPrint(); }
@Test public void renderSimpleBeanPrefixed() throws Exception { view.setPrefixJson(true); renderSimpleBean(); assertTrue(response.getContentAsString().startsWith(")]}', ")); }
/** * Set the {@code ObjectMapper} for this view. * If not set, a default {@link ObjectMapper#ObjectMapper() ObjectMapper} will be used. * <p>Setting a custom-configured {@code ObjectMapper} is one way to take further control of * the JSON serialization process. The other option is to use Jackson's provided annotations * on the types to be serialized, in which case a custom-configured ObjectMapper is unnecessary. */ public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; configurePrettyPrint(); }
/** * Whether to use the default pretty printer when writing the output. * This is a shortcut for setting up an {@code ObjectMapper} as follows: * <pre class="code"> * ObjectMapper mapper = new ObjectMapper(); * mapper.configure(SerializationFeature.INDENT_OUTPUT, true); * </pre> * <p>The default value is {@code false}. */ public void setPrettyPrint(boolean prettyPrint) { this.prettyPrint = prettyPrint; configurePrettyPrint(); }