后台提供API给前端调用,一般使用
HttpMessageConverter
把Json字符串转换成对象,如果存在格式问题则会抛出异常HttpMessageNotReadableException
。但是后台拿不到原始的Json字符串,不方便定位到确切的格式错误。 本文介绍一个简易方法,可以在出错时,展示Json原文信息。
一开始想寻找其他方式,当抛出异常的时候,就从HttpServletRequest
读取body内容。但是做不到,因为在做Json读取的时候,InputStream已经被读取了,无法再次获取到body内容。所以只能通过自定义MessageConverter
的方式。
其实也可以,把request中inpustream读取出来保存,再提供一个getInputStream,参见 How to read request.getInputStream() multiple times
import com.google.common.io.CharStreams;
public class HttpMessageConverter extends GsonHttpMessageConverter {
@Override
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
TypeToken<?> token = getTypeToken(type);
return readTypeToken(token, inputMessage);
}
private Object readTypeToken(TypeToken<?> token, HttpInputMessage inputMessage) throws IOException {
Reader json = new InputStreamReader(inputMessage.getBody(), getCharset(inputMessage.getHeaders()));
//先获取Json原始字符串
final String jsonBody = CharStreams.toString(json);
try {
return this.getGson().fromJson(jsonBody, token.getType());
} catch (JsonParseException ex) {
//解析失败,则在异常中输出Json原始字符串
throw new HttpMessageNotReadableException(String.format("JSON parse error: %s%n%s", ex.getMessage(), jsonBody), ex);
}
}
private Charset getCharset(HttpHeaders headers) {
if (headers == null || headers.getContentType() == null || headers.getContentType().getCharset() == null) {
return DEFAULT_CHARSET;
}
return headers.getContentType().getCharset();
}
}
spring-mvc.xml
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="com.tenmao.HttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
假设参数对象如下:
@Data
public class Person {
private String name;
private Integer age;
private Boolean gender;
private List<String> hobbies;
}
如果收到错误格式的Json消息,则会抛出异常(hobbies应该是一个数组,参数中是字符串basketball)
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 5 column 14 path $.hobbies
{
"name": "tenmao",
"gender": true,
"age": 28,
"hobbies": "basketball"
}; nested exception is com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 5 column 14 path $.hobbies