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

时间:2009-04-08 21:43:36

标签: java xml json serialization

我正在开发一个RESTful Web服务。

我有一堆实体类(主要是JPA实体,还有其他bean)。

有很多对象映射,序列化,绑定和诸如此类的库。我正在寻找一个能让我:

的人
  • 将实体序列化为XML和JSON

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

    必须支持观看次数。通过视图,我指的是指定要序列化的实体属性的子集的方法。有关示例,请参阅Yahoo!中的Retrieving Partial Resources。社交平台API。我也不希望它无限期地递归:

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

    例如,实体Person可能包含观看次数fullsimple。在请求simple的{​​{1}}视图时,只会对属性PersonidfirstName进行序列化。在请求lastName视图时,属性fullmotherfather自己)也会被序列化,但只能使用Persons视图(所以它不会归咎于祖父母。)

    JSON序列化必须“自然”,即在Javascript中有意义的东西。这意味着我想要正确的整数,布尔值和空值,我不想要额外的对象包装器或试图捕获整个XML Infoset的东西。

    对于XML,必须配置序列化以使用空元素来序列化空值,而不是XML Schema的simple属性。

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

    • 未定义的xsi:nil="true"属性(视图中不存在):

      friends
    • 空数组,人没有朋友:

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

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

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

    合并到现有属性中,而不是创建新属性。

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

    获得此XML时:

    <person>
        <friends></friends>
    </person>
    

    并传递<person> <lastName>Bon Jovi</lastName> <friends></friends> </person> 对象,库应该:

    Person

    例如,它不应触及实体person.setLastName("Bon Jovi"); person.setFriends(new ArrayList()); 和/或清除它firstName

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

    这些更新/补丁是图书馆不得仅返回DTO的原因:因为那时father可能意味着“未设置”或“什么也不做”。

嗯,就是这样。我一直在说“必须”很多,我现在意识到:)图书馆不需要实际提供,但必须有一种方式以干净的方式添加功能(=不会以重写一切的方式更容易)。

2 个答案:

答案 0 :(得分: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有点棘手,但不是太糟糕

    • 我假设您已经有一些方法可以将要合并的对象编入索引(比如某种地图)
    • 我假设您已经有一些方法可以知道哪个属性是唯一标识对象的键(我假设姓氏只是为了得到重点,因为它会产生错误的密钥)
    • XML:对于这种类型的使用,我建议使用一个用于xml的SAX阅读器 - 你需要一个堆栈来跟踪你要添加数据的对象。 SAX阅读器会告诉您看到的标签,然后给出这些标签的值。你也可以在这里使用XML pull,这往往会更快一点
    • JSON:看看一些开源JSON库并做一些调整。解析JSON非常简单,而且这些工具往往很小,所以这应该不是什么大问题。或者,您可以编写一个ANTLR(或其他生成器)解析器来读取JSON并根据需要使用它。

答案 1 :(得分:1)

对于它的价值,Jackson具有开箱即用的部分更新:

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

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

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