2013-10-15 90 views
3

杰克逊允许您自定义序列化EnumMap关键字的方式吗?举例来说,如果我有杰克逊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例外。

任何想法???

回答

4

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

我试过了,我得到了预期的输出。希望这可以帮助!

+0

这种方法适用于HashMap的,虽然在我的特殊情况下'MyKey'是一个枚举,我实际上使用了EnumMap。不幸的是,即使使用这个更新的序列化器,杰克逊也输出枚举的名称(),而不是使用我定义的getId()方法,即使使用@JsonValue。你知道另一种可能适用于EnumMap的方法吗? – ManRow

+0

你可以发布一个链接到你的代码有'enum's?我将'MyKey'(从前面的例子)转换为'enum'('getKey'方法完好无损),并且序列化输出与之前相同。 – Jackall

+0

但是如果你使用'EnumMap'而不是HashMap?我已经在原帖中更新了我的代码,以反映这个 – ManRow