001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.http.converter.json; 018 019import java.io.IOException; 020 021import com.fasterxml.jackson.core.JsonGenerator; 022import com.fasterxml.jackson.databind.ObjectMapper; 023 024import org.springframework.http.MediaType; 025 026/** 027 * Implementation of {@link org.springframework.http.converter.HttpMessageConverter} that can read and 028 * write JSON using <a href="https://wiki.fasterxml.com/JacksonHome">Jackson 2.x's</a> {@link ObjectMapper}. 029 * 030 * <p>This converter can be used to bind to typed beans, or untyped {@code HashMap} instances. 031 * 032 * <p>By default, this converter supports {@code application/json} and {@code application/*+json} 033 * with {@code UTF-8} character set. This can be overridden by setting the 034 * {@link #setSupportedMediaTypes supportedMediaTypes} property. 035 * 036 * <p>The default constructor uses the default configuration provided by {@link Jackson2ObjectMapperBuilder}. 037 * 038 * <p>Compatible with Jackson 2.6 and higher, as of Spring 4.3. 039 * 040 * @author Arjen Poutsma 041 * @author Keith Donald 042 * @author Rossen Stoyanchev 043 * @author Juergen Hoeller 044 * @author Sebastien Deleuze 045 * @since 3.1.2 046 */ 047public class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter { 048 049 private String jsonPrefix; 050 051 052 /** 053 * Construct a new {@link MappingJackson2HttpMessageConverter} using default configuration 054 * provided by {@link Jackson2ObjectMapperBuilder}. 055 */ 056 public MappingJackson2HttpMessageConverter() { 057 this(Jackson2ObjectMapperBuilder.json().build()); 058 } 059 060 /** 061 * Construct a new {@link MappingJackson2HttpMessageConverter} with a custom {@link ObjectMapper}. 062 * You can use {@link Jackson2ObjectMapperBuilder} to build it easily. 063 * @see Jackson2ObjectMapperBuilder#json() 064 */ 065 public MappingJackson2HttpMessageConverter(ObjectMapper objectMapper) { 066 super(objectMapper, MediaType.APPLICATION_JSON, new MediaType("application", "*+json")); 067 } 068 069 /** 070 * Specify a custom prefix to use for this view's JSON output. 071 * Default is none. 072 * @see #setPrefixJson 073 */ 074 public void setJsonPrefix(String jsonPrefix) { 075 this.jsonPrefix = jsonPrefix; 076 } 077 078 /** 079 * Indicate whether the JSON output by this view should be prefixed with ")]}', ". Default is false. 080 * <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. 081 * The prefix renders the string syntactically invalid as a script so that it cannot be hijacked. 082 * This prefix should be stripped before parsing the string as JSON. 083 * @see #setJsonPrefix 084 */ 085 public void setPrefixJson(boolean prefixJson) { 086 this.jsonPrefix = (prefixJson ? ")]}', " : null); 087 } 088 089 090 @Override 091 @SuppressWarnings("deprecation") 092 protected void writePrefix(JsonGenerator generator, Object object) throws IOException { 093 if (this.jsonPrefix != null) { 094 generator.writeRaw(this.jsonPrefix); 095 } 096 String jsonpFunction = 097 (object instanceof MappingJacksonValue ? ((MappingJacksonValue) object).getJsonpFunction() : null); 098 if (jsonpFunction != null) { 099 generator.writeRaw("/**/"); 100 generator.writeRaw(jsonpFunction + "("); 101 } 102 } 103 104 @Override 105 @SuppressWarnings("deprecation") 106 protected void writeSuffix(JsonGenerator generator, Object object) throws IOException { 107 String jsonpFunction = 108 (object instanceof MappingJacksonValue ? ((MappingJacksonValue) object).getJsonpFunction() : null); 109 if (jsonpFunction != null) { 110 generator.writeRaw(");"); 111 } 112 } 113 114}