解決SpringMVC返回Json資料格式不嚴謹報異常的問題(草稿未完成)
阿新 • • 發佈:2019-01-29
週末除錯程式的時候發現的該問題,表現如下:
當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 /> 並宣告
然後寫一個類MyJacksonConverter, 程式碼照搬MappingJacksonHttpMessageConverter,writeInternal部分重新寫一個
這樣就可以對所有欄位加上引號了。
搞定
當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); } }
這樣就可以對所有欄位加上引號了。
搞定