【问题标题】:Deserializing selected property names only (Jackson)仅反序列化选定的属性名称 (Jackson)
【发布时间】:2016-08-15 18:12:54
【问题描述】:

假设我们有以下 JSON,

{
    "id": "imgsId1",
    "type": "Fruits",
    "name": "Tropical",
    "image":
     {
         "url": "images/img1.jpg",
         "width": 300,
         "height": 300
    },
    "thumbnail":
    {
        "url": "images/thumbnails/img11.jpg",
        "width": 50,
        "height": 50
    }
}

在 Java 类中,我们拥有与上述 JSON 匹配的所有字段。

每次要反序列化的字段列表取决于发送信息的客户。

例如,对于客户 1,我们只想读回以下值,(即使在 JSON 中提供,也跳过其他属性)

String[] propertiesToFilter1 = {"type","image.url"};

例如,对于客户 2,我们想要回读以下值,(并跳过其他属性,即使在 JSON 中提供)

String[] propertiesToFilter2 = {"type","image.url", "image.width"};

当使用Jackson反序列化JSON时,是否可以提供上面包含需要反序列化的字段的数组,

ImageInfo obj1 = (ImageInfo)objectMapper.readValue(jsonStr, ImageInfo.class);

更新:

在网上研究时,我发现其中一个选项可以通过使用

FilterProvider filterProvider = new SimpleFilterProvider().addFilter("filterName1", 
                    SimpleBeanPropertyFilter.serializeAllExcept(propertiesToFilter1));

objectMapper.setFilters(filterProvider);

但我认为这很好,如果我们想继续为多个客户重复使用相同的“filterName1”。

在这种情况下,情况略有不同,因为我们自定义了每个客户可以更新的字段列表。所以每个客户都有不同的 JSON 字段列表,他们可以在不同的类中更新。

如果我们开始为每个客户定义不同的过滤器名称,这将是一个很长的列表,并且查找会对性能产生影响。

所以一直在寻找解决方案,当使用 objectMapper.readValue() 方法构造返回对象时,我可以在其中检查允许在运行时处理的字段列表。

更新 2(2016 年 4 月 25 日):

浏览其他杰克逊问题,在这里看到了类似的问题,

Jackson Dynamic filtering of properties during deserialization

通过创建自定义“静态 ObjectMapper”使用下面列出的方法,这种方法的问题是我们多次运行反射 API。

  • Jackson 解析器第一次使用 将 JSON 反序列化为 Java 对象时的反射 API

  • 第二次,因为我们无法获取所有由 Jackson 解析器,为了将数据填充到另一个对象中,我们再次需要运行反射 API 来填充另一个对象。

这可能会导致大量开销。

使用上面提供的链接中定义的方法,我认为使用“BeanDeserializerModifier”似乎是最好的方法。现在的问题是,由于我们也使用基于工厂的方法来初始化 ObjectMapper,我们不想为不同的客户硬编码所有数组。

想检查是否可以向 String[] 数组提供运行时要考虑的属性列表给“BeanDeserializerModifier”?

类似的东西,

String[] propertiesToFilter2 = {"type","image.url", "image.width"};

BeanDeserializerModifier curBeanDeserializerModifier = 
            getBeanDeserializerModifierInstance();

curBeanDeserializerModifier.setPropertiesToConsider(propertiesToFilter2);

谢谢

【问题讨论】:

  • 你怎么知道你必须为哪个客户反序列化东西,什么时候不需要?
  • 这个 JSON 文件可以通过 Web(表单 POST)或 FTP 接收。对于所有客户,我们使用相同的 Java 类文件。

标签: java json jackson deserialization


【解决方案1】:

【讨论】:

  • 感谢您的回复。如果我想跳过考虑所有客户文件的这些字段,@JsonIgnoreProperties({"pw", "email", "name", "devices", "lastModified", "created"}) 将起作用。 这里的场景是针对不同的客户,我们要自定义我们要考虑的字段
  • 不同客户端输入数据是否存在差异
【解决方案2】:

我不确定是否可以使用注释动态配置反序列化。

我建议用static ObjectMapper 创建一个类。在这个类中,您可以创建不同的反序列化实现。然后,您的应用程序的业务逻辑应该决定应该为哪个客户使用哪个实现。在您的不同实现中,您可以像使用注释一样配置ObjectMapper

第二种解决方案可以是为每个客户反序列化完整的json,并让业务逻辑决定使用 Pojo 的哪些字段/对象。这也需要在您的应用程序中实现。

在业务逻辑中实施配置的好处是,您将拥有更简洁的代码和一个为每个客户完成配置的地方。


static ObjectMapper information

【讨论】:

  • 请检查我更新的 cmets。这会对性能产生影响,因为我们需要多次运行 Java Reflection API。
  • @mike39 最后,您必须在objectMapper 中注册BeanDeserializerModifier 才能使用它。还是我错了?
猜你喜欢
  • 2017-09-15
  • 2018-10-31
  • 2016-02-11
  • 1970-01-01
  • 2017-11-29
  • 2013-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多