Man*_*olo 52 java json arraylist jackson json-deserialization
我有一个使用Jersey构建的REST服务,并部署在AppEngine中.REST服务实现使用application/json媒体类型的动词PUT.数据绑定由Jackson执行.
动词使用JSON表示的企业部门关系
{"name":"myEnterprise", "departments":["HR","IT","SC"]}
Run Code Online (Sandbox Code Playgroud)
在客户端,我使用gson将JSON表示转换为java对象.然后,我将对象传递给我的REST服务,它工作正常.
问题:
当我的JSON表示在集合中只有一个项目时
{"name":"myEnterprise", "departments":["HR"]}
Run Code Online (Sandbox Code Playgroud)
该服务无法反序列化该对象.
ATTENTION: /enterprise/enterprise: org.codehaus.jackson.map.JsonMappingException:
Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token at
[Source: org.mortbay.jetty.HttpParser$Input@5a9c5842; line: 1, column: 2
Run Code Online (Sandbox Code Playgroud)
正如其他用户所报告的那样,解决方案是添加标志ACCEPT_SINGLE_VALUE_AS_ARRAY(例如,Jersey:无法从String中反序列化ArrayList的实例).然而,我并不是在控制ObjectMapper,因为在服务方面它是由Jackson透明地制作的.
题:
有没有办法在服务端配置ObjectMapper以启用ACCEPT_SINGLE_VALUE_AS_ARRAY?注释?web.xml中?
代码细节
Java对象:
@XmlRootElement
public class Enterprise {
private String name;
private List<String> departments;
public Enterprise() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getDepartments() {
return departments;
}
public void setDepartments(List<String> departments) {
this.departments = departments;
}
}
Run Code Online (Sandbox Code Playgroud)
REST服务端:
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/enterprise")
public Response putEnterprise(Enterprise enterprise,
@Context HttpServletRequest req){
...
}
Run Code Online (Sandbox Code Playgroud)
客户端:
...
String jsonString = "{\"name\":\"myEnterprise\", \"departments\":[\"HR\"]}";
Enterprise enterprise = gson.fromJson(jsonString, Enterprise.class);
System.out.println(gson.toJson(enterprise));
response = webResource
.type(MediaType.APPLICATION_JSON)
.put(ClientResponse.class,enterprise);
if (response.getStatus() >= 400) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
...
Run Code Online (Sandbox Code Playgroud)
Man*_*olo 50
这是我老问题的解决方案:
我实现了自己的ContextResolver以启用DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY功能.
package org.lig.hadas.services.mapper;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
@Produces(MediaType.APPLICATION_JSON)
@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper>
{
ObjectMapper mapper;
public ObjectMapperProvider(){
mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
Run Code Online (Sandbox Code Playgroud)
在web.xml中,我将我的包注册到servlet定义中......
<servlet>
<servlet-name>...</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>...;org.lig.hadas.services.mapper</param-value>
</init-param>
...
</servlet>
Run Code Online (Sandbox Code Playgroud)
......所有其他的都是由泽西/杰克逊透明完成的.
Kan*_*thy 21
将此属性设置为ObjectMapper实例,
objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
Run Code Online (Sandbox Code Playgroud)
Ric*_*hen 20
你试试吗
[{"name":"myEnterprise", "departments":["HR"]}]
Run Code Online (Sandbox Code Playgroud)
方括号是关键点.
从Jackson 2.7.x +开始,有一种方法可以注释成员变量本身:
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<String> newsletters;
Run Code Online (Sandbox Code Playgroud)
更多信息在这里:Jackson @JsonFormat
对于通过搜索错误消息找到此问题的人,如果您在@JsonProperty批注中输入了错误,List从而用单值字段的名称注释了-typed属性,那么您也会看到此错误:
@JsonProperty("someSingleValuedField") // Oops, should have been "someMultiValuedField"
public List<String> getMyField() { // deserialization fails - single value into List
return myField;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
153208 次 |
| 最近记录: |