我们的应用程序中有两个部分:
服务器 - 提供REST服务
客户端 - 通过Spring restTemplate使用它们
除了HTTP状态之外,我们的服务器还返回一个带有JSON的HTTP主体,它详细描述了错误.所以,我已经为restTemplate添加了自定义错误处理程序来处理一些编码为非错误的错误 - 它有助于解析HTTP正文.
但是,在HTTP/1.1 401 Unauthorized的情况下,我通过解析HTTP正文获得异常.所有其他错误代码都处理得很好(400,402等)我们正在使用普通服务器逻辑,在发生错误时发送HTTP响应,对于不同类型的错误没有特殊规则:
writeErrorToResponse(int status, String errMsg, HttpServletResponse resp) throws IOException {
response.setStatus(status);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
String message = String.format("{\"error\":\"%s\"}", StringUtils.escapeJson(errMsg));
resp.getWriter().println(message);
}
Run Code Online (Sandbox Code Playgroud)
但在客户端只有HTTP/1.1 401抛出异常 - "java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode"
我做了一些调试,发现问题的原因是SimpleClientHttpResponse中的代码:
HttpURLConnection.getInputStream()
使用Fiddler进行跟踪会有以下响应:在客户端上解析消息是正确的:
HTTP/1.1 402 Payment Required
X-Powered-By: Servlet/3.0
Content-Type: application/json
Content-Language: en-GB
Content-Length: 55
Connection: Close
Date: Sat, 25 May 2013 10:10:44 GMT
Server: WebSphere Application Server/8.0
{"error":"I cant find that user. Please try …Run Code Online (Sandbox Code Playgroud) 我有一个基于json的REST Web服务实现使用:Jetty,Jersey,Jersey-JSON使用Jackson.
我的一个方法接收一个Person实例,它有一个List <String>类型的字段.即:
Public class Person {
List<String> names;
}
Run Code Online (Sandbox Code Playgroud)
如果我用一系列名字来称呼它,一切正常!例如:
{ "names" : [ "Jhon", "Doe" ] }
Run Code Online (Sandbox Code Playgroud)
但是如果这个人只有一个名字,我的客户就会创建一个单独的值元素,例如:
{ "names" : "Jhon" }
Run Code Online (Sandbox Code Playgroud)
当我尝试使用单个值调用服务时,我得到一个例外:
Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
Run Code Online (Sandbox Code Playgroud)
题:
我应该如何创建/配置我的Web服务,以便能够在将数组字段作为单个元素发送给我时反序列化数组字段.
-
我已经读过:
和
这是指最后一个答案:
Jersey客户端无法反序列化json服务 - 异常(无法反序列化实例)
但这些都没有解决问题.
先感谢您!
我最近将我的Spring版本从3.1.2升级到3.2.0.我发现像包装根元素这样的JSON属性,防止在ObjectMapper中定义的空值不再起作用.
这是代码片段
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="true" />
<property name="ignoreAcceptHeader" value="false" />
<property name="mediaTypes" >
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
Run Code Online (Sandbox Code Playgroud)
和JSON转换器
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="customJacksonObjectMapper"/>
<property name="supportedMediaTypes" value="application/json"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
对象映射器代码
public class CustomJacksonObjectMapper extends ObjectMapper {
@SuppressWarnings("deprecation")
public CustomJacksonObjectMapper() {
super();
final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
this.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
this.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
this.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false);
this.setDeserializationConfig(this.getDeserializationConfig().withAnnotationIntrospector(introspector));
this.setSerializationConfig(this.getSerializationConfig().withAnnotationIntrospector(introspector));
}
}
Run Code Online (Sandbox Code Playgroud)
杰克逊版
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
<version>1.9.7</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
可能是什么问题?任何指针都表示赞赏.