最近做公司的api平台,用到了rop,帮助节省了很多工作量,先感谢作者。但是用到json序列化时遇到一个问题:服务端有一个打印:“输出响应”输出的json和返回到客户端的json不一致,发现是json序列化的代码不一致。
代码如下:
AnnotationServletServiceRouter 类
writeResponse方法
private void writeResponse(Object ropResponse, HttpServletResponse httpServletResponse, MessageFormat messageFormat, String jsonpCallback) { try { if (!(ropResponse instanceof ErrorResponse) && messageFormat == MessageFormat.stream) { if (logger.isDebugEnabled()) { logger.debug("使用{}输出方式,由服务自身负责响应输出工作.", MessageFormat.stream); } return; } if (logger.isDebugEnabled()) { logger.debug("输出响应:" + MessageMarshallerUtils.getMessage(ropResponse, messageFormat)); } RopMarshaller ropMarshaller = xmlMarshallerRop; String contentType = APPLICATION_XML; if (messageFormat == MessageFormat.json) { ropMarshaller = jsonMarshallerRop; contentType = APPLICATION_JSON; } httpServletResponse.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*"); httpServletResponse.addHeader(ACCESS_CONTROL_ALLOW_METHODS, "*"); httpServletResponse.setCharacterEncoding(Constants.UTF8); httpServletResponse.setContentType(contentType); if (jsonpCallback != null) { httpServletResponse.getOutputStream().write(jsonpCallback.getBytes()); httpServletResponse.getOutputStream().write('('); } ropMarshaller.marshaller(ropResponse, httpServletResponse.getOutputStream()); if (jsonpCallback != null) { httpServletResponse.getOutputStream().write(')'); httpServletResponse.getOutputStream().write(';'); } } catch (IOException e) { throw new RopException(e); } }
里面输出响应的方法MessageMarshallerUtils.getMessage 对应类:
MessageMarshallerUtils初始化ObjectMapper方法
static { SerializationConfig serializationConfig = jsonObjectMapper.getSerializationConfig(); serializationConfig = serializationConfig.without(SerializationConfig.Feature.WRAP_ROOT_VALUE) .with(SerializationConfig.Feature.INDENT_OUTPUT); }
输出到客户端ropMarshaller.marshaller对应的类:
JacksonJsonRopMarshaller类初始化objectMapper方法
private ObjectMapper getObjectMapper() throws IOException { if (this.objectMapper == null) { ObjectMapper objectMapper = new ObjectMapper(); AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(); SerializationConfig serializationConfig = objectMapper.getSerializationConfig(); serializationConfig = serializationConfig.without(SerializationConfig.Feature.WRAP_ROOT_VALUE) .with(SerializationConfig.Feature.INDENT_OUTPUT) .withSerializationInclusion(JsonSerialize.Inclusion.NON_NULL) .withSerializationInclusion(JsonSerialize.Inclusion.NON_EMPTY) .withAnnotationIntrospector(introspector); objectMapper.setSerializationConfig(serializationConfig); this.objectMapper = objectMapper; } return this.objectMapper; }
这两个类的初始化不一致,导致了如下情况下会出bug
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "getDeliveryNoticestatusresponse") public class GetDeliveryStatusResponse { @XmlElement(name = "iscancle") private boolean Cancle; public boolean getCancle() { return Cancle; } public void setCancle(boolean iscancle) { Cancle = iscancle; } }
返回response的类如上所示,
那么在控制台用log4j打印的为:
2015-06-27 10:46:40,633 [org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean#0-2] DEBUG [com.rop.impl.AnnotationServletServiceRouter] - 输出响应:{"cancle":false}
而返回到客户端的打印为:
2015-06-27 10:46:40,642 [main] DEBUG [com.rop.client.DefaultRopClient] - {"iscancle":false}
即处理打印时方法没有加
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(); serializationConfig.withAnnotationIntrospector(introspector);
没有考虑jaxb的注解别名,希望作者在MessageMarshallerUtils的初始化objectMapper时上能加上以上代码
最后还是很感谢作者的rop