【问题标题】:Serialize a custom map with Jackson使用 Jackson 序列化自定义地图
【发布时间】:2014-04-16 07:52:13
【问题描述】:

我想将自定义 Map 序列化为 JSON。

实现map接口的类如下:

public class MapImpl extends ForwardingMap<String, String> {
//ForwardingMap comes from Guava
    private String                  specialInfo;

    private HashMap<String, String> delegate;

    @Override
    protected Map<String, String> delegate() {
        return this.delegate;
    }
// some getters....
 }

如果我现在打电话

    ObjectMapper mapper = new ObjectMapper();
    mapper.writeValue(new File("/somePath/myJson.json"), objectOfMapImpl);

Jackson 将序列化地图并忽略变量specialInfo

我用JsonSerializer 的自定义实现尝试了一些东西,但我最终得到了这个sn-p:

    ObjectMapper mapper = new ObjectMapper();

    SimpleModule module = new SimpleModule("someModule");



       module.addSerializer(CheapestResponseDates.class, new JsonSerializer<MapImpl>() {

            @Override
            public void serialize(final MapImpl value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException {
CheapestResponseDurations.class);
// how to serialize the map here? maybe be in a data node...
                jgen.writeStartObject();
                jgen.writeObjectField("info", value.getInfo());
                jgen.writeEndObject();
            }
        });


    mapper.registerModule(module);

我正在使用 JDK 1.7 和 Jackson 2.3.1

【问题讨论】:

  • 你能改变MapImpl类吗?这个属性有getter/setter吗?
  • 可以,它有一个用于 info 属性的 getter。我还为底层地图添加了一个公共方法,用于测试目的。但是 MapImpl 必须实现 Map。

标签: java json serialization jackson


【解决方案1】:

您可以利用@JsonAnySetter/@JsonAnyGetter 注释,如this blog post 中所述。正如您所提到的,您的自定义地图类必须实现 Map 接口,您可以提取一个单独的“bean”接口并告诉 Jackson 在通过 @JsonSerialize(as = ...) 注释进行序列化时使用它。

我稍微修改了你的例子来说明它是如何工作的。请注意,如果您想将 json 字符串反序列化回您的地图对象,您可能需要做一些其他的技巧。

public class MapSerialize  {
public static interface MyInterface {
    String getSpecialInfo();

    @JsonAnyGetter
    Map<String, String> delegate();
}

@JsonSerialize(as = MyInterface.class)
public static class MyImpl extends ForwardingMap<String, String> implements MyInterface {

    private String                  specialInfo;
    private HashMap<String, String> delegate = new HashMap<String, String>();

    public Map<String, String> delegate() {
        return this.delegate;
    }

    @Override
    public String getSpecialInfo() {
        return specialInfo;
    }

    public void setSpecialInfo(String specialInfo) {
        this.specialInfo = specialInfo;
    }

    @Override
    public String put(String key, String value) {
        return delegate.put(key, value);
    }
}

public static void main(String[] args) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    MyImpl objectOfMapImpl = new MyImpl();
    objectOfMapImpl.setSpecialInfo("specialInfo");
    objectOfMapImpl.put("XXX", "YYY");
    String json = mapper.writeValueAsString(objectOfMapImpl);
    System.out.println(json);
}

}

【讨论】:

  • 这不是一个选项,因为我不能以这种方式更改 MapImpl,它必须实现 Map
  • 我已经更新了我的答案以使用中间接口进行序列化。
  • 当我的班级实现 java.util.Set 而不是 Map 时,有没有办法存档? @JsonAnyGetter 仅适用于地图...
  • 我找到了类似 Alexeys answer 的方法,只需删除 @JsonAnyGetter 并添加到该界面中的所有方法 @JsonGetter :)
猜你喜欢
  • 1970-01-01
  • 2014-08-02
  • 2013-10-10
  • 2017-03-02
  • 2016-01-11
  • 2019-08-10
  • 2021-03-03
  • 1970-01-01
  • 2017-05-20
相关资源
最近更新 更多