Java 序列化/反序列化自定义映射<;键,对象>;在杰克逊

Java 序列化/反序列化自定义映射<;键,对象>;在杰克逊,java,serialization,jackson,deserialization,Java,Serialization,Jackson,Deserialization,我有一个非常简单的映射,我想在Jackson中序列化和反序列化,但我无法让它工作 我尝试了以下方法: @JsonSerialize(keyUsing=TurnKeySerializer.class) @JsonDeserialize(keyUsing = TurnKeyDeserializer.class) Map<TurnKey, PlayerTurn> publicTurns = new TreeMap<>(); @JsonIgnoreProperties(igno

我有一个非常简单的映射,我想在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);
    }

}
@JsonSerialize(keyUsing=TurnKeySerializer.class)
@JsonDeserialize(keyUsing=TurnKeyDeserializer.class)
Map publicTurns=new TreeMap();
@JsonIgnoreProperties(ignoreUnknown=true)
@数据//创建Getter/Setter等
公共类交钥匙实现{
私人最终国际转机号码;
私有最终字符串用户名;
公共交钥匙(整数交钥匙号、字符串用户名){
这个.turnNumber=turnNumber;
this.username=用户名;
}
@凌驾
公共内部比较(交钥匙o){
int v=整数.valueOf(turnNumber).compareTo(o.getTurnNumber());
如果(v!=0){
返回v;
}
返回username.compareTo(o.getUsername());
}
@凌驾
公共字符串toString(){
返回“{”+
“车次号:”+车次号+
,用户名:“+username+”“+
"}";
}
公共类Turnkeys序列化程序扩展JsonSerializer{
@凌驾
public void serialize(交钥匙值、JsonGenerator gen、SerializerProvider序列化程序)引发IOException、JsonProcessingException{
if(null==值){
抛出新IOException(“无法将对象序列化为json,要序列化的输入对象为null”);
}
StringWriter编写器=新的StringWriter();
ObjectMapper mapper=新的ObjectMapper();
writeValue(writer,value);
gen.writeFieldName(writer.toString());
}
}
公共类TurnKeyDeserializer扩展了KeyDeserializer{
私有静态最终ObjectMapper mapper=新ObjectMapper();
@凌驾
公共交钥匙反序列化密钥(字符串密钥、反序列化上下文ctxt)引发IOException、JsonProcessingException{
返回mapper.readValue(key,TurnKey.class);
}
}
但我有个例外


com.fasterxml.jackson.databind.JsonMappingException:无法从START\u数组令牌中反序列化java.util.LinkedHashMap的实例

您需要在TurnKey中定义/重写fromString()方法。jackson将使用toString()进行序列化,使用fromString()进行反序列化。这就是“找不到(Map)密钥反序列化器”的原因由以下原因引起的错误消息
中的意思:com.fasterxml.jackson.databind.JsonMappingException:在com.fasterxml.jackson.databind.deser.DeserializerCache.\u handleUnknownKeyDeserializer(DeserializerCache.java:584)
中找不到类型[简单类型,类号为asgari.civilization.server.model.TurnKey]的(映射)密钥反序列化器


不需要自定义密钥反序列化器。

您能解释一下为什么要使用自定义(de)密钥反序列化器吗TurnKey的序列化程序?您尝试过没有?序列化的json可以吗?@Tom,因为您是必需的。否则Jackson无法映射。我尝试过没有,这就是导致我出现这种情况的原因。我只是在反序列化时出错,所以我相信可以。toString()至少在我看来是正确的。如果我在没有任何序列化器/反序列化器的情况下使用交钥匙,我会得到一个异常。
原因:com.fasterxml.jackson.databind.JsonMappingException:找不到类型[simple type,class no.asgari.civilization.server.model.TurnKey]的(映射)密钥反序列化器位于com.fasterxml.jackson.databind.deser.DeserializerCache.\u handleUnknownKeyDeserializer(DeserializerCache.java:584)
带有非字符串键的映射确实需要自定义反序列化程序。但是序列化此类映射只需调用键对象的toString方法。请检查序列化json中的内容是否与您期望的输入内容相同。您也可以将该json键与存储库对象一起使用,从db中获取新对象