1. 程式人生 > >解決SpringMVC返回Json資料格式不嚴謹報異常的問題(草稿未完成)

解決SpringMVC返回Json資料格式不嚴謹報異常的問題(草稿未完成)

週末除錯程式的時候發現的該問題,表現如下:
     當springmvc配合jackson返回json資料不是嚴格按照json格式返回時,如服務端返回:{“age":20} 
    同域請求不報錯,瀏覽器直接請求也不報錯可以正常返回,但跨域用jquery請求時會報一個unexpected end of data的錯誤,也就是jquery解析json的返回資料異常。注意不是請求的引數,而是服務端返回的內容。

於是查網上資料,要修改spring的配置,AnnotationMethodHandlerAdapter這段要注入一個Converter來代替預設的org.springframework.http.converter.json.MappingJacksonHttpMessageConverter。
例如:http://www.360doc.com/content/13/0514/17/11947209_285403916.shtml

按照這個操作屢試不成功,經除錯發現系統在啟動時生成了兩個AnnotationMethodHandlerAdapter,顯式配置成單例也不行。
再搜發現是 <mvc:annotation-driven /> 和AnnotationMethodHandlerAdapter的衝突造成的,使用<mvc:annotation-driven />會預設生成兩個bean,DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter。找到原因就好辦了,首先去掉<mvc:annotation-driven /> 並宣告
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>  
	
	<bean class ="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
	    <property name="messageConverters"> 
		  <list> 		   	
		   	<bean class="com.abc.MyJacksonConverter"/>
		  </list> 
		</property> 
</bean>  

然後寫一個類MyJacksonConverter, 程式碼照搬MappingJacksonHttpMessageConverter,writeInternal部分重新寫一個
	@Override
	protected void writeInternal(Object o, HttpOutputMessage outputMessage)
			throws IOException, HttpMessageNotWritableException {

		JsonEncoding encoding = getEncoding(outputMessage.getHeaders().getContentType());
		JsonGenerator jsonGenerator =
				this.objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
		try {
			if (this.prefixJson) {
				jsonGenerator.writeRaw("{} && ");
			}
			//允許單引號
			this.objectMapper.configure(org.codehaus.jackson.JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
			//欄位和值都加引號
			this.objectMapper.configure(org.codehaus.jackson.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
			//數字也加引號
			this.objectMapper.configure(org.codehaus.jackson.JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
			this.objectMapper.configure(org.codehaus.jackson.JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS, true);
			this.objectMapper.writeValue(jsonGenerator, o);
		}
		catch (JsonGenerationException ex) {
			throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
		}
	}

這樣就可以對所有欄位加上引號了。

搞定