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 的方法吗?
您能否发布一个指向您的代码的链接,其中包含enum
s?我将MyKey
(来自上一个示例)转换为enum
(getKey
方法完好无损),序列化输出与之前相同。
但是如果你使用EnumMap
而不是HashMap呢?我已经更新了原始帖子中的代码以反映这一点
EnumMap
s 使用specialized serializer 进行序列化,因此在序列化密钥时不会拾取您的自定义序列化程序。我尝试覆盖MyKey
中的toString()
实现并使用设置SerializationFeature.WRITE_ENUMS_USING_TO_STRING
,即使这似乎也不起作用。因此,我不确定这是否可能。
FWIW,更高版本有一些修复;特别是2.4.4。以上是关于Jackson EnumMap 密钥序列化的主要内容,如果未能解决你的问题,请参考以下文章
使用 writeValueAsString 序列化对象后 Jackson 反序列化失败