如何配置Jackson使其能够反序列化特殊集合?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何配置Jackson使其能够反序列化特殊集合?相关的知识,希望对你有一定的参考价值。

[我想知道如何配置Jackson来对“特殊”集合(不可变或所收集流的结果)中包含的对象的序列化列表进行反序列化。

这是我的问题,由于某些原因,我需要在jackson中声明de type,因为我需要能够反序列化所有内容并恢复所有类型。


public static class Sink 
    private List items;

    public Sink setItems(final List items) 
        this.items = items;
        return this;
    

    public List getItems() 
        return this.items;
    


public static void main(String[] args) throws Exception 
    final ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    mapper.registerModule(new Jdk8Module());
    mapper.registerModule(new AfterburnerModule());
    mapper.enableDefaultTyping(NON_FINAL, JsonTypeInfo.As.PROPERTY);

    String content = mapper.writeValueAsString(new Sink().setItems(List.of()));
    System.out.println(content);
    Sink result = mapper.readValue(content, Sink.class);

但是这会对集合产生不良影响。content值是:


    "@class": "api.Sink",
    "items": ["java.util.ImmutableCollections$ListN", []]

而且不幸的是,java.util.ImmutableCollections.*没有默认的构造函数(有意义)。

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.util.ImmutableCollections $ ListN (no Creators, like default construct, exist): no default no-arguments constructor found

我想知道如何迫使杰克逊将这类对象反序列化为ArrayList或任何类型的列表。

我想将其配置为将列表的所有子类型反序列化为ArrayList / LinkedList,或者在序列化以更改集合的类型时进行反序列化

((java 12 /杰克逊2.9.7)

答案

不幸的是,这不可能。一个对象必须具有默认构造函数才能使用Jackson进行反序列化(Jackson如何知道如何填充其构造函数?)如果要将对象反序列化为ArrayList,则必须将immutableCollection转换为ArrayList,然后对其进行序列化

另一答案

您可以使用特定的反序列化器对其进行点缀,例如使用Mixin。

解串器的示例:

class UnmodifiableSetDeserializer extends JsonDeserializer<Set> 

@Override
public Set deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException 
    ObjectMapper mapper = (ObjectMapper) jp.getCodec();
    JsonNode node = mapper.readTree(jp);
    Set<Object> resultSet = new HashSet<Object>();
    if (node != null) 
        if (node instanceof ArrayNode) 
            ArrayNode arrayNode = (ArrayNode) node;
            Iterator<JsonNode> nodeIterator = arrayNode.iterator();
            while (nodeIterator.hasNext()) 
                JsonNode elementNode = nodeIterator.next();
                resultSet.add(mapper.readValue(elementNode.traverse(mapper), Object.class));
            
         else 
            resultSet.add(mapper.readValue(node.traverse(mapper), Object.class));
        
    
    return Collections.unmodifiableSet(resultSet);


您可以在Spring security here的CoreJacksont2Module中找到完整的示例,>

以上是关于如何配置Jackson使其能够反序列化特殊集合?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring Boot 为嵌套实体配置 Jackson 反序列化器

使用 Jackson 将 JSON 反序列化为 ArrayList<POJO>

如何使用 Jackson 将原始 JSON 反序列化为 Java 对象

你能配置 Spring 控制器特定的 Jackson 反序列化吗?

Jackson XML 反序列化问题

可以将 Jackson 配置为反序列化 JSON 密钥(非值)吗?