【问题标题】:Jackson serialize a subset of a map杰克逊序列化地图的一个子集
【发布时间】:2014-08-10 17:47:34
【问题描述】:

我有一张地图,我想用 Jackson 序列化它,但只想序列化它的一个子集。假设我有一个简单的地图如下:

final Map<String, String> map = new HashMap<>();
map.put("key 1", "value 1");
map.put("key 2", "value 2");
map.put("_internal key 1", "value 3");
map.put("_internal key 2", "value 4");

然后在序列化这个时,我想过滤掉任何以_开头的项目,这样序列化的表示就是{'key 1': 'value 1','key 2': 'value 2'}

我开始查看 @JsonFilter,但除了针对基本类型的非常简单的示例之外,找不到任何示例,而且似乎没有任何东西可以帮助这种更高级的过滤类型。

提供这种自定义序列化的最佳方式是什么?

这是使用 Jackson 2.4,以防万一。

【问题讨论】:

  • 你为什么不过滤地图,并将结果序列化?使用番石榴:Map&lt;String, String&gt; filtered = Maps.filterKeys(map, s -&gt; !s.startsWith("_"));
  • 好问题。我不是直接序列化地图,它是对象的一部分,也是我正在序列化的对象。因此,我无法直接访问地图,因此如果在序列化之前无法过滤。
  • 你不能提供一个 getter 来返回你正在序列化的对象中的过滤后的地图(并用 @JsonIgnore 注释完整的地图)吗?
  • 从映射中删除无效键,然后将其序列化。
  • 是的,我可以这样做,但是我需要在使用这种类型的地图的任何地方都这样做(这是相当多的地方)。如果我可以使用自定义序列化程序,我只需要这样做一次。

标签: java serialization jackson


【解决方案1】:

您可以通过定义Jackson filter 来实现此目的,该Jackson filter 输出不以下划线开头的键,并通过the annotation introspector 为所有Map 类启用此过滤器。这是一个例子:

public class JacksonMapSubset {

    public static void main(String[] args) throws JsonProcessingException {
        final Map<String, String> map = new HashMap<>();
        map.put("key 1", "value 1");
        map.put("key 2", "value 2");
        map.put("_internal key 1", "value 3");
        map.put("_internal key 2", "value 4");

        ObjectMapper mapper = new ObjectMapper();

        SimpleFilterProvider filters = new SimpleFilterProvider();
        final String filterName = "exclude-starting-with-underscore";
        mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
            @Override
            public Object findFilterId(Annotated a) {
                if (Map.class.isAssignableFrom(a.getRawType())) {
                    return filterName;
                }
                return super.findFilterId(a);
            }
        });
        filters.addFilter(filterName, new SimpleBeanPropertyFilter() {
            @Override
            protected boolean include(BeanPropertyWriter writer) {
                return true;
            }

            @Override
            protected boolean include(PropertyWriter writer) {
                return !writer.getName().startsWith("_");
            }
        });

        mapper.setFilters(filters);
        System.out.println(mapper.writeValueAsString(map));
    }
}

输出:

{"key 1":"value 1","key 2":"value 2"}

【讨论】:

  • 正是我想要的。谢谢!
猜你喜欢
  • 2012-01-11
  • 1970-01-01
  • 2016-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-05
  • 1970-01-01
相关资源
最近更新 更多