Jackson EnumMap 密钥序列化

Posted

技术标签:

【中文标题】Jackson EnumMap 密钥序列化【英文标题】:Jackson EnumMap key serialization 【发布时间】:2013-10-22 17:42:04 【问题描述】:

Jackson 是否允许您自定义它如何序列化 EnumMap 键?例如,如果我有

public enum MyKey

    ABC, DEF, XYZ;

    public String getKey()
    
        return "my-key-" + ordinal();
    

还有一些

public class MyObject

    private final Map<MyKey,String> map = new EnumMap<>(MyKey.class);

    public MyObject()
    
        map.put(MyKey.ABC, "foo");
        map.put(MyKey.DEF, "bar");
        map.put(MyKey.XYZ, "baz");
    

    public Map<MyKey,String> getMap()
    
        return map;
    

然后杰克逊会将MyObject序列化为

"map":"ABC":"foo","DEF":"bar","XYZ":"baz".

相反,我希望它像序列化一样

"map":"my-key-0":"foo","my-key-1":"bar","my-key-2":"baz"。我不想覆盖任何 toString() 以使其正常工作。这在杰克逊有可能吗?

我试过这样做:

public class MyKeySerializer extends JsonSerializer<MyKey>

    @Override
    public void serialize(MyKey value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException
    
        jgen.writeString(value.getKey());
    

然后添加

public class MyObject

    ...

    @JsonSerialize(keyUsing = MyKeySerializer.class)
    public Map<MyKey,String> getMap()
    
        return map;
    

    ...

但由于org.codehaus.jackson.JsonGenerationException: Can not write text value, expecting field name 异常而失败。

有什么想法吗???

【问题讨论】:

【参考方案1】:

MyKeySerializer 中使用jgen.writeFieldName(value.getKey()); 而不是jgen.writeString(value.getKey());。正如错误消息所示,Jackson 希望您在序列化键时编写字段名称(而不是直接输入文本)。

我尝试这样做,我得到了预期的输出。希望这会有所帮助!

【讨论】:

这种方法适用于 HashMap,尽管在我的特殊情况下MyKey 是一个枚举,而我实际上使用的是一个 EnumMap。不幸的是,即使使用这个更新的序列化程序,Jackson 也会输出枚举的 name(),而不是使用我定义的 getId() 方法,即使使用 @JsonValue。你知道另一种可能适用于 EnumMap 的方法吗? 您能否发布一个指向您的代码的链接,其中包含enums?我将MyKey(来自上一个示例)转换为enumgetKey 方法完好无损),序列化输出与之前相同。 但是如果你使用EnumMap而不是HashMap呢?我已经更新了原始帖子中的代码以反映这一点 EnumMaps 使用specialized serializer 进行序列化,因此在序列化密钥时不会拾取您的自定义序列化程序。我尝试覆盖MyKey 中的toString() 实现并使用设置SerializationFeature.WRITE_ENUMS_USING_TO_STRING,即使这似乎也不起作用。因此,我不确定这是否可能。 FWIW,更高版本有一些修复;特别是2.4.4。

以上是关于Jackson EnumMap 密钥序列化的主要内容,如果未能解决你的问题,请参考以下文章

json之jackson序列化反序列化探究(二)

json之jackson的常用全局配置以及自定义序列化规则

Jackson序列化和反序列化

使用 writeValueAsString 序列化对象后 Jackson 反序列化失败

Java下用Jackson进行JSON序列化和反序列化(转)

利用Jackson序列化实现数据脱敏