代码之家  ›  专栏  ›  技术社区  ›  Jaka Jančar

部分bean序列化和反序列化+合并

  •  3
  • Jaka Jančar  · 技术社区  · 17 年前

    我正在开发一个restful web服务。

    我有很多实体类(主要是jpa实体,但也有其他bean)。

    有大量的对象映射、序列化、绑定和其他库。我在找一个能让我:

    • 将实体序列化为xml和json

      序列化必须支持使用 吸气剂 ,而不仅仅是对象字段。

      它必须支持 意见 . 我所说的视图是指一种指定要序列化的实体属性子集的方法。例如,请参见 Retrieving Partial Resources 在雅虎!社交平台API。我也不希望它无限地重复:

      视图应该定义a)要在实体中公开的属性和b)每个属性的视图(如果它们是实体本身)。

      例如,实体 Person 可能有意见 full simple . 当要求 简单的 A视图 ,仅属性 id , firstName lastName 将被序列化。当要求 满的 视图,属性 mother father (哪些是 Persons 它们本身)也将被序列化,但仅限于 简单的 视图(这样就不会再出现在祖父母身上)。

      json序列化必须是 “自然” ,即在javascript中有什么意义。这意味着我需要适当的整数、布尔值和空值,而不需要额外的对象包装器或试图捕获整个xml信息集的东西。

      对于XML,必须能够将序列化配置为使用 空元素 用于序列化空值,而不是XML架构的 xsi:nil="true" 属性。

      此外,必须使用嵌套元素序列化数组,以便能够区分空数组和给定视图中不存在的属性:

      • 未定义 friends 属性(视图中不存在):

        <person>
        </person>
        
      • 空阵,人无友:

        <person>
            <friends></friends>
        </person>
        
    • 反序列化XML和JSON并将数据合并到现有实体中

      现在这是困难的部分。接下来的两个连接:

      反序列化 部分对象 必须是可能的(类似于视图,但是没有预先定义哪些属性)。

      合并 进入现有属性,而不是创建新属性。

      这有点难以解释。大多数库反序列化为Java对象,但在那时,丢失了未定义属性和null /空属性(如JavaScript /JSON,XML,如上所述,PHP,…)之间的区别。

      当获得此XML时:

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

      通过了 对象,库应:

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

      它不应该触及实体 第一名字 和/或清除 父亲 ,例如。

      当然,对于列表,这应该更复杂。我希望配置一个id属性,由它决定是更新嵌套实体还是创建一个新实体。

      这些更新/修补程序是库不能只返回DTO的原因:因为当时 null 可能意味着“不安”或“什么都不做”。

    好吧,就这样。我一直在说“必须”很多,我现在意识到:)这个库实际上不需要提供这个功能,但是必须有一种方法以干净的方式添加这个功能(不是以一种可以使重写一切变得更容易的方式)。

    2 回复  |  直到 17 年前
        1
  •  1
  •   Scott Stanchfield    17 年前

    我不知道现有的库是否能满足您的所有需求,但是,假设您需要实现某些功能:

    • 基于bean属性编写xml或json非常简单:

      • 看看使用apache commons beanutils能够获得所有属性值( http://commons.apache.org/beanutils/ )尤其是propertyutils类。
      • 递归地使用beanutils来遍历整个对象图-小心循环-您需要一个集合或其他东西来跟踪您已经看到的内容
      • xml:看看xmlencoder-它使用javabean属性创建xml
    • 阅读:一种方法可能是使用现有的libs(用于json或xml)创建对象,然后处理对象之间的属性合并。XmlDecoder类可以读取BeanXML(假设您使用XmlEncoder创建它)。这种方法的一个棘手的部分是知道一个值何时被“设置”为空,而XML中却没有设置。这种方法还有创建一堆新对象的额外开销。

    • 否则,读取json或xml会有点困难,但不会太糟

      • 我想你已经有了一些方法来索引你想合并的对象(比如某种地图)
      • 我假设你已经有办法知道哪个属性是唯一标识对象的键(我假设姓氏只是为了说明问题,因为它会生成一个坏键)
      • XML:对于这种类型的使用,我推荐一个XML的SAX阅读器——您需要一个堆栈来跟踪要向其中添加数据的对象。sax阅读器告诉您看到了哪些标记,然后给出这些标记的值。您也可以在这里使用xml pull,这会更快一些
      • json:看看一些开源json库并做一些调整。json的解析非常简单,而且这些工具往往非常小,所以这不应该是什么大事。或者,您可以编写一个antlr(或其他生成器)解析器来读取json,并根据您的需要进行处理。
        2
  •  1
  •   StaxMan    15 年前

    为了它的价值, Jackson 有现成的部分更新:

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

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

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