有没有办法在类的List属性中使用注释来在ACCEPT_SINGLE_VALUE_AS_ARRAY
中使用Jackson
?我使用Spring并获得以下异常
嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:不能 从VALUE_STRING标记中反序列化java.util.ArrayList的实例
假设我有一个课程如下:
public class MyClass {
private List < String > value;
}
我的JSON结构如下:
案例1:
[{"operator": "in", "value": ["Active"], "property": "status"}]
案例2:
[{"operator": "like", "value": "aba", "property": "desc"}]
我应该使用什么注释让框架知道我希望在反序列化时将这两种情况视为相同。
更新 为了更加清晰,我在本文中将更新移到了答案中。
答案 0 :(得分:21)
您可以使用@JsonFormat注释
public class MyClass {
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List < String > value;
}
要使用此功能,您需要拥有Jackson版min 2.7.0
。您还可以使用其他可用的JsonFormat Features
@Autowired private ObjectMapper mapper;
//...
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
Initializer Class
。Jackson
Bean Configuration
这些可以解决问题,但会为每个deserialization
进程激活它。
答案 1 :(得分:6)
我会创建一个自定义JsonDeserializer
,我将处理这两种情况并使用反序列化器注释值类属性。
解串器:
public class StringListDeserializer extends JsonDeserializer<List<String>>{
@Override
public List<String> deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
List<String> ret = new ArrayList<>();
ObjectCodec codec = parser.getCodec();
TreeNode node = codec.readTree(parser);
if (node.isArray()){
for (JsonNode n : (ArrayNode)node){
ret.add(n.asText());
}
} else if (node.isValueNode()){
ret.add( ((JsonNode)node).asText() );
}
return ret;
}
}
MyClass的:
public class MyClass {
.
@JsonDeserialize(using = StringListDeserializer.class)
private List<String> value;
.
}
希望它有所帮助。
顺便说一句:如果有一种方法只用注释处理这种情况,我也想知道它。
答案 2 :(得分:3)
为了清楚起见,我只是回答了我自己的问题。其中一个答案是升级到更高版本,以便我可以使用注释。由于项目的依赖性限制,我无法做到这一点。
因此,根据Michal Foksa的回答,我通过创建自定义反序列化器解决了我的问题。如下:
在我的财产上:
@JsonDeserialize(using = CustomStringDeserializer.class)
private List<String> value;
我的解串器:
public class CustomStringDeserializer extends JsonDeserializer<List<String>>{
@Override
public List<String> deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature. ACCEPT_SINGLE_VALUE_AS_ARRAY);
return mapper.readValue(p, List.class);
}
}
答案 3 :(得分:2)
对于春季项目添加
spring.jackson.deserialization.accept-single-value-as-array=true
在属性文件中将适用于 spring 处理的所有反序列化,即使在控制器类方法中,其中 @RequestBody
用于 API。
答案 4 :(得分:0)
如果该项目是Spring项目,则可以将此属性放入application.properties
中:
spring.jackson.deserialization.UNWRAP_SINGLE_VALUE_ARRAYS=true