在Jackson中序列化/反序列化自定义的Map<Key, Object>

5
我是一名有用的助手,可以为您翻译文本。

我有一个非常简单的Map,想要在Jackson中进行序列化和反序列化,但我无法使其正常工作。

我尝试了以下方法:

@JsonSerialize(keyUsing=TurnKeySerializer.class)
@JsonDeserialize(keyUsing = TurnKeyDeserializer.class)
Map<TurnKey, PlayerTurn> publicTurns = new TreeMap<>();

@JsonIgnoreProperties(ignoreUnknown = true)
@Data //Creates Getter/Setter etc
public class TurnKey implements Comparable<TurnKey> {
    private final int turnNumber;
    private final String username;

    public TurnKey(int turnNumber, String username) {
        this.turnNumber = turnNumber;
        this.username = username;
    }

    @Override
    public int compareTo(TurnKey o) {
        int v = Integer.valueOf(turnNumber).compareTo(o.getTurnNumber());
        if (v != 0) {
            return v;
        }
        return username.compareTo(o.getUsername());
    }

    @Override
    public String toString() {
        return "{" +
                "turnNumber:" + turnNumber +
                ", username:'" + username + "'" +
                "}";
    }


public class TurnKeySerializer extends JsonSerializer<TurnKey> {
    @Override
    public void serialize(TurnKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        if (null == value) {
            throw new IOException("Could not serialize object to json, input object to serialize is null");
        }
        StringWriter writer = new StringWriter();
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(writer, value);
        gen.writeFieldName(writer.toString());
    }
}


public class TurnKeyDeserializer extends KeyDeserializer {
    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public TurnKey deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        return mapper.readValue(key, TurnKey.class);
    }

}

但是我遇到了一个异常

com.fasterxml.jackson.databind.JsonMappingException: 无法从 START_ARRAY 令牌反序列化为 java.util.LinkedHashMap 的实例


你能解释一下为什么在TurnKey中使用自定义的(de)serializer吗?你尝试过不用它吗? - Tom
序列化的 JSON 数据没问题吗? - Tom
@Tom 因为这是必需的。否则Jackson无法映射。我之前尝试过不加,这就导致了现在的问题。我只在反序列化时遇到错误,所以我认为是这个原因。至少在我的看来,toString()方法是正确的。 - Shervin Asgari
只有在具有非常特定的非默认映射要求时,您才需要自定义序列化程序。Jackson可以在没有它们的情况下正常工作。您应该尝试再次使用没有自定义(反)序列化程序的方式。我看不到您的代码中有任何无法工作的问题,尽管您没有包含所有代码。 - Tom
2
如果我在没有任何序列化程序/反序列化程序的情况下使用TurnKey,我会得到一个异常。Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class no.asgari.civilization.server.model.TurnKey] at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:584) - Shervin Asgari
1
具有非字符串键的映射需要自定义反序列化器。但是这种映射的序列化将简单地调用键对象的toString方法。检查序列化的JSON中是否包含预期的输入内容。您还可以使用该JSON键与存储库对象一起从数据库中获取新对象。 - Japheth Ongeri - inkalimeva
1个回答

4
你需要在TurnKey中定义/覆盖fromString()方法。Jackson将使用toString()序列化和fromString()反序列化。这就是错误消息中“找不到(Map)Key deserializer”的含义:Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class no.asgari.civilization.server.model.TurnKey] at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:584)
不需要自定义KeyDeserializer。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接