简体   繁体   English

如何使用JAXB处理“空对象”(非空)?

[英]How can I deal with “null objects” (not null) using JAXB?

I am writing a software to manage box events. 我正在编写用于管理框事件的软件。 The core classes are BoxEvent , Fight , and Fighter . 核心类是BoxEventFightFighter A box event has a list of all available fighters as well as of fights which contain references to particular fighters. 一场拳击比赛列出了所有可用的战士以及包含对特定战士的引用的战斗列表。

For the references each Fighter gets a unique ID which is used as @XmlID and is referenced in the list of fights through @XmlIDREF . 对于参考,每个Fighter都有一个唯一的ID,该ID用作@XmlID并通过@XmlIDREF在战斗列表中进行@XmlIDREF JAXB (un)marshalling works fine. JAXB(un)编组工作正常。 An XML file looks similar to this one: 一个XML文件看起来与此类似:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<boxEvent>
<fighter uuid="id_efc8c3f6-f95c-424f-a6d4-f9fde1cdd3a1">
    <birthday>1995-08-31</birthday>
    <firstName>Donald</firstName>
    <lastName>Duck</lastName>
    <gender>MALE</gender>
    <weight>62.0</weight>
</fighter>
<fighter uuid="id_356f82d1-14a7-4cce-bf5b-18d6e59eddfe">
    <birthday>1994-08-25</birthday>
    <firstName>Mickey</firstName>
    <lastName>Mouse</lastName>
    <gender>MALE</gender>
    <weight>56.9</weight>
</fighter>
<fighter uuid="id_c4b8d4c9-de24-4bfb-bad8-36a5bd4433b5">
    <birthday>1991-08-12</birthday>
    <firstName>Minnie</firstName>
    <lastName>Mouse</lastName>
    <gender>FEMALE</gender>
    <weight>40.8</weight>
</fighter>
<fights>
    <fighterInBlueCorner>id_356f82d1-14a7-4cce-bf5b-18d6e59eddfe</fighterInBlueCorner>
    <fighterInRedCorner>id_efc8c3f6-f95c-424f-a6d4-f9fde1cdd3a1</fighterInRedCorner>
</fights>
</boxEvent>

Now the problem is that a fight may not yet have two fighters, but only one. 现在的问题是,一场战斗可能还没有两架战斗机,而只有一架。 This is internally implemented by using a special Fighter object (a null object ) and not null and this special object is not in the list of all boxers (because it is no real boxer, rather an implementation detail). 这是通过使用特殊的Fighter对象( null对象 )而不是 null在内部实现的,并且该特殊对象不在所有拳击手的列表中(因为它不是真正的拳击手,而是实现的详细信息)。 That means: A missing fighter can be marshalled in a fight (because it has an ID since technically speaking it is a Fighter ), but it cannot be unmarshalled, because this ID won't be found in the list of all fighters. 这意味着:可以在战斗中将丢失的战斗机编组(因为从技术上讲它是一个Fighter ,因此具有ID),但是不能将其编组,因为在所有战斗机列表中都找不到该ID。

Whereas I already found solutions to store null (eg this question ) I could not find a good one for the "null object". 尽管我已经找到了存储null解决方案(例如, 此问题 ),但我找不到适合“ null对象”的解决方案。

So my question is: Is it possible to use a @XmlJavaTypeAdapter or any other technique to replace the null object by null for marshalling? 所以我的问题是:是否可以使用@XmlJavaTypeAdapter或任何其他技术将null对象替换为null进行编组? And when unmarshalling do the opposite: create this special null object for a missing fighter in one corner? 当解组时,做相反的事情:为一个角落里的失踪战士创建这个特殊的空对象?

I am also happy to hear about other ideas how to deal with that problem or if you could point me in the right direction. 我也很高兴听到有关如何解决该问题的其他想法,或者是否可以为我指明正确的方向。 Thanks! 谢谢!

No, the @XmlJavaTypeAdapter will not fire on nulls. 不, @XmlJavaTypeAdapter不会在null上触发。 Rather, you should have a "default" of whatever it is you need. 相反,您应该具有所需的“默认值”。 Then the unmarshalling code will overwrite the fighter if it is indeed in the XML. 然后,如果确实存在于XML中,则解组代码将覆盖战斗机。

@XmlElement
private Fighter fighter = DEFAULT_FIGHTER_OR_NULL_OR_WHATEVER;

My initial question may have been formulated a bit too complicated – sorry! 我最初的问题可能有点太复杂了-对不起! :) I finally found out by myself how to solve my problem properly – well, by just using a @XmlJavaTypeAdapter in the Fight class. :)我终于自己找到了解决问题的方法-好吧,只需在Fight类中使用@XmlJavaTypeAdapter The adapter is incredibly simple and looks as follows: 适配器非常简单,外观如下:

public class FighterXmlAdapter extends XmlAdapter<Fighter, Fighter> {

  @Override
  public Fighter unmarshal(final Fighter fighter) throws Exception {
    return fighter == null ? NULL_FIGHTER : fighter;
  }

  @Override
  public Fighter marshal(final Fighter fighter) throws Exception {
    return fighter.equals(NULL_FIGHTER) ? null : fighter;
  }

}

So in case only the fighter in the red corner is present, the serialized XML will look like this: 因此,如果只有战斗机出现在红色角落,则序列化的XML将如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<boxEvent>
  <fighter uuid="id_efc8c3f6-f95c-424f-a6d4-f9fde1cdd3a1">
    <birthday>1995-08-31</birthday>
    <firstName>Donald</firstName>
    <lastName>Duck</lastName>
    <gender>MALE</gender>
    <weight>62.0</weight>
  </fighter>
  <fighter uuid="id_356f82d1-14a7-4cce-bf5b-18d6e59eddfe">
    <birthday>1994-08-25</birthday>
    <firstName>Mickey</firstName>
    <lastName>Mouse</lastName>
    <gender>MALE</gender>
    <weight>56.9</weight>
  </fighter>
  <fights>
    <fighterInRedCorner>id_efc8c3f6-f95c-424f-a6d4-f9fde1cdd3a1</fighterInRedCorner>
  </fights>
</boxEvent>

That means the internal implementation of the missing fighter is not exposed and when loading the file a NULL_FIGHTER is instantiated. 这意味着不会公开缺少战斗机的内部实现,并且在加载文件时会实例化NULL_FIGHTER Pretty simple, but took me a while to figure it out ... ;) 很简单,但是花了我一段时间才解决...;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM