部分Bean的序列化和反序列化+合并

3

我正在开发一个RESTful网络服务。

我有一堆实体类(大多是JPA实体,但也包括其他bean)。

市面上有很多对象映射、序列化、绑定等库。我正在寻找一个能够让我能够:

  • Serialize the entities to XML and JSON

    Serialization MUST support using getters, not only object fields.

    It MUST support views. By views I mean a way to specify a subset of the properties of the entity, which are to be serialized. For an example, see Retrieving Partial Resources in the Yahoo! Social Platform API. I also don't want it to recurse indefinitely deep:

    The view should define a) properties to be exposed in the entity and b) a view for each of them (if they're entities themselves).

    For example, the entity Person might have views full and simple. When requesting a simple view of a Person, only properties id, firstName and lastName would be serialized. When requesting a full view, the properties mother and father (which are Persons themselves) would also be serialized, but only with the simple view (so it wouldn't recurse to grandparents).

    The JSON serialization MUST be "natural", i.e. what would make sense in Javascript. That means I want proper integers, booleans and nulls and I don't want extra object wrappers or something that tries to capture the entire XML Infoset.

    For XML, it MUST be possible to configure the serialization to use empty elements for serializing nulls, not XML Schema's xsi:nil="true" attributes.

    Additionally, arrays must be serialized using nested elements so it's possible to differentiate between empty arrays and properties which aren't present in a given view:

    • Undefined friends property (not present in view):

      <person>
      </person>
      
    • Empty array, person has no friends:

      <person>
          <friends></friends>
      </person>
      
  • Deserialize XML and JSON and merge the data into existing entities

    Now this is the difficult part. The next two are connected:

    Deserialization of partial objects MUST be possible (analogous to views, but which properties are present is not defined in advance).

    Merging into existing properties, not creating new ones.

    This is a bit tricky to explain. Most libraries deserialize into Java objects, but at that time, the distinction between an undefined property and a null/empty property (as it exists in Javascript/JSON, XML as described above, PHP, ...) is lost.

    When being given this XML:

    <person>
        <lastName>Bon Jovi</lastName>
        <friends></friends>
    </person>
    

    and being passed a Person object, the library should:

    person.setLastName("Bon Jovi");
    person.setFriends(new ArrayList());
    

    It shouldn't touch the entities firstName and/or clear it's father, for example.

    Of course with lists this should be more complex. I would expect to configure an id property, by which it would decide whether to update the nested entity or create a new one.

    These updates/patches are a reason why the library MUST NOT just return a DTO: because at that time a null might either mean "unset" or "do nothing".

好的,这就是全部内容了。我现在意识到我一直在说“必须”的话 :) 图书馆实际上不需要提供这个功能,但必须有一种干净的方式来添加功能(即不会使重写所有内容更容易的方式)。

2个回答

1

就此而言,Jackson具备开箱即用的部分更新功能:

ObjectMapper mapper = new ObjectMapper();
Bean existing = ...;
mapper.updatingReader(existing).readValue(jsonSource);

它还可以转换兼容类型(类似于序列化为JSON,读回不同类型)。

对于XML部分,您可以使用JAXB,尽管据我所知它只能完成绑定。


1

我不知道存在能够满足你所有需求的库,但是假设你需要实现一些东西:

  • 基于bean属性编写XML或JSON非常简单:

    • 考虑使用Apache Commons BeanUtils来获取所有属性值(http://commons.apache.org/beanutils/)。特别是PropertyUtils类。
    • 递归使用BeanUtils遍历整个对象图-小心循环-您需要在侧面使用Set或其他东西来跟踪您已经看到的内容
    • XML:查看XMLEncoder-它使用JavaBean属性创建XML
  • 对于阅读:一种方法可能是使用现有库(用于JSON或XML)创建对象,然后处理对象之间的属性合并。 XMLDecoder类可以读取bean XML(假设您使用XMLEncoder创建它)。这种方法的棘手部分是要知道何时将值“设置”为null而不是在XML中未设置。此方法还具有创建大量新对象的额外开销。

  • 否则,阅读JSON或XML有点棘手,但并不太糟糕

    • 我假设您已经有某种方式索引要合并的对象(例如某种Map)
    • 我假设您已经有某种方式知道哪个属性是唯一标识对象的关键(我假设姓氏只是为了说明问题,因为它会成为一个糟糕的关键字)
    • XML:对于这种类型的使用,我建议使用SAX阅读器来阅读xml-您需要一个堆栈来跟踪添加数据的对象。 SAX阅读器告诉您看到了哪些标记,然后给出了这些标记的值。您还可以在此处使用XML pull,它往往会更快一些
    • JSON:查看一些开源JSON库并进行一些调整。 JSON很容易解析,这些工具往往非常小,因此这不应该是大问题。或者,您可以编写ANTLR(或其他生成器)解析器来读取JSON并按照自己的意愿处理它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接