杰克逊 - Map 实现的序列化

时间:2021-08-19 14:42:06

I have following class:

我有以下课程:

public class Some implements Map<String, Object>{
    private Map<String, Object> innerMap;
    //implementation that can only set innerMap in constructor and cannot add or remove values
}

The problem is that I cannot deserialize this in jackson correctly. If I serialize without default typing, it is OK, since it is serialized as {"one":"two"} and deserialized correctly (I had to implement deserializer with

问题是我无法正确地在杰克逊中反序列化。如果我在没有默认输入的情况下序列化,那就没关系,因为它被序列化为{“one”:“two”}并且正确反序列化(我必须实现反序列化器

return new Some(jp.readValueAs(new TypeReference<HashMap<String,Object>>(){}));

When I use default typing turned on, this is serialized as

当我使用默认打字时,这被序列化为

["com.class.Some",{"one":"two"}]

But deserialization is throwing

但反序列化正在抛弃

com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.util.HashMap

Any thoughts?

有什么想法吗?

2 个解决方案

#1


0  

Annotate your constructor with @JsonCreator:

使用@JsonCreator注释您的构造函数:

public static void main(String[] args) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

    Some some = new Some(new HashMap<String, Object>() {{put("a", 1);}});

    String json = mapper.writeValueAsString(some);
    System.out.println("serialized  : " + json);

    some = mapper.readValue(json, Some.class);
    System.out.println("deserialized: " + some);
}

// Read only delegating Map
public static class Some extends AbstractMap<String, Object> {
    private Map<String, Object> delegate;

    @JsonCreator
    public Some(Map<String, Object> delegate) {
        this.delegate = Collections.unmodifiableMap(delegate);
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        return delegate.entrySet();
    }
}

#2


0  

This is what I needed - custom deserializer:

这就是我需要的 - 自定义反序列化器:

public class SomeDeserializer extends JsonDeserializer<Some> {

    @Override
    public Object deserializeWithType(JsonParser jsonParser, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
        return typeDeserializer.deserializeTypedFromObject(jsonParser, ctxt);
    }

    @SuppressWarnings("unchecked")
    @Override
    public Some deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException {
        JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(
                ctxt.getTypeFactory().constructMapType(Map.class, String.class, Object.class));

        return new Some((Map) deserializer.deserialize(jp, ctxt, new HashMap<>()));
    }
}

#1


0  

Annotate your constructor with @JsonCreator:

使用@JsonCreator注释您的构造函数:

public static void main(String[] args) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

    Some some = new Some(new HashMap<String, Object>() {{put("a", 1);}});

    String json = mapper.writeValueAsString(some);
    System.out.println("serialized  : " + json);

    some = mapper.readValue(json, Some.class);
    System.out.println("deserialized: " + some);
}

// Read only delegating Map
public static class Some extends AbstractMap<String, Object> {
    private Map<String, Object> delegate;

    @JsonCreator
    public Some(Map<String, Object> delegate) {
        this.delegate = Collections.unmodifiableMap(delegate);
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        return delegate.entrySet();
    }
}

#2


0  

This is what I needed - custom deserializer:

这就是我需要的 - 自定义反序列化器:

public class SomeDeserializer extends JsonDeserializer<Some> {

    @Override
    public Object deserializeWithType(JsonParser jsonParser, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
        return typeDeserializer.deserializeTypedFromObject(jsonParser, ctxt);
    }

    @SuppressWarnings("unchecked")
    @Override
    public Some deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException {
        JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(
                ctxt.getTypeFactory().constructMapType(Map.class, String.class, Object.class));

        return new Some((Map) deserializer.deserialize(jp, ctxt, new HashMap<>()));
    }
}

相关文章