【问题标题】:How to Customizing JAXBContext Unmarshaller for complex case如何为复杂情况自定义 JAXBContext Unmarshaller
【发布时间】:2012-08-16 09:52:49
【问题描述】:

我有关于将 XML 转换为 Java 对象的问题,在这里我使用 JAXB。
就我而言:

XML 数据:

<persons>
  <person>
     <name>Aris Tonar</name>
     <age />
     <nickname />
     <saldo />
  </person>
</persons>

XML 数据的 JAVA 类:

public class Person{
   private String name;
   private Integer age;
   private String nickName;
   private Integer id;
   private Double saldo;

   /**
   *Setter and Getter
   */

}

当我使用标准 JAXBContext Unmarshaller 代码将其解析为 Java 对象时。带代码:

JAXBContext context = JAXBContext.newInstance(Person.class.getPackage().getName());
Unmarshaller unmarshaller = context.createUnmarshaller();
JAXBElement element = (JAXBElement) unmarshaller.unmarshal(new StreamSource(new StringReader(stringOfXmlData.toString())));
Person obj = (Person) element.getValue();

它会给出结果: 人名 = “Aris Tonar”
人年龄 = null
人物昵称 = ""
人 id = null
人萨尔多 = null

但不是我想要的结果,我希望 JAXB 会给出结果:

人名 = “Aris Tonar”
人年龄 = 0
人物昵称 = ""
人 id = null
人萨尔多 = 0

  1. 我希望在 XML DATA 中声明的每个元素都将:如果指定了值,jaxb 会将其解释为正常值(如 name 元素),但如果未指定值,则 jaxb 会将其解释为默认值(如年龄、昵称、saldo 元素)
  2. 如果元素未在 XML 数据中声明,则 jaxb 会将其解释为 null。(如 id 元素)

我是否可以这样做?可能与自定义 JAXBContext 代码有关??

【问题讨论】:

    标签: java xml jaxb


    【解决方案1】:
    @XmlType(name = "person", propOrder = {"name", "age", "nickName" , "saldo"})
    public class Person {
    
    private String name;
    private Integer age;
    private String nickName;
    private Integer id;
    private Double saldo;
    
    public Person(String name, Integer age, String nickName, Integer id, Double saldo) {
      this.name = name;
      this.age = age;
      this.nickName = nickName;
      this.id = id;
      this.saldo = saldo;
    }
    
    public Person() {
      //jaxb constructor
    }
    
    @XmlElement(defaultValue="0")
    public Integer getAge() {
      return age;
    }
    
    @XmlTransient
    public Integer getId() {
      return id;
    }
    
    @XmlElement(defaultValue="")
    public String getName() {
      return name;
    }
    
    @XmlElement(name="nickname" , defaultValue="")
    public String getNickName() {
     return nickName;
    }
    
    @XmlElement(defaultValue="0")
    public Double getSaldo() {
      return saldo;
    }
    
    public void setAge(Integer age) {
      this.age = age;
    }
    
    public void setId(Integer id) {
      this.id = id;
    }
    
    public void setName(String name) {
      this.name = name;
    }
    
    public void setNickName(String nickName) {
      this.nickName = nickName;
    }
    
    public void setSaldo(Double saldo) {
      this.saldo = saldo;
    }
    
    
    }
    

    【讨论】:

    • 非常感谢 Err,您的解释是我的解决方案,
    • 你好 Err,我还有其他问题。我的 Java 类以及该类中的 xml 注释是来自 xsd 文件的 JAXB 绑定的结果,在我的情况下,JAXB 绑定为属性定义了“@XmlAttribute” ,那么我如何为该属性分配 defaultValue 。谢谢
    • 您在 xsd 文件中设置默认值。 &lt;xs:attribute name="lang" type="xs:string" default="EN"/&gt;
    【解决方案2】:

    这有点麻烦,但你应该能够使用类型适配器来实现你想要的:

    public class Person{
       private String name;
       @XmlJavaTypeAdapter(IntegerZeroDefaultAdapter.class)
       @XmlSchemaType(name = "integer")
       private Integer age;
       private String nickName;
       private Integer id;
       @XmlJavaTypeAdapter(DoubleZeroDefaultAdapter.class)
       @XmlSchemaType(name = "double")
       private Double saldo;
       // ...    
    }
    
    public class IntegerZeroDefaultAdapter extends XmlAdapter<String, Integer> {
      public String marshal(Integer n) {
        return String.valueOf(n);
      }
    
      public Integer unmarshal(String val) {
        if(val == null) return null;
        else if("".equals(val)) return 0;
        else return Integer.valueOf(val);
      }
    }
    
    // likewise for DoubleZeroDefaultAdapter
    

    您不需要名称或昵称的适配器,除非您要使用的默认值不是空字符串 - 字符串值的默认值是缺少元素意味着 null 和指定的 - 但是 -空元素表示空字符串,记住在 XML 中 &lt;nickname /&gt; 完全等同于 &lt;nickname&gt;&lt;/nickname&gt;

    【讨论】:

    • 虽然在重新阅读文档时,我会说 Err 使用 @XmlElement(defaultValue = "...") 的答案是一个更好的解决方案。
    • 感谢 Ian Roberts,虽然 Err 的回答更简单,但您的解释是我处理复杂元素(如 java.util.Date 或其他非包装类(自定义类))的解决方案。
    【解决方案3】:

    如果在声明成员时使用默认值实例化成员,则应该解决第一个问题。

    试试:

    public class Person{
     private String name = "";
     private Integer age = 0;
     private String nickName; = ""
     private Integer id = 0;
     private Double saldo =0.0;
    

    hth,
    麦克莱克斯

    【讨论】:

      【解决方案4】:

      我你用cxf-codegen-plugin,你可以(从XSD/WSDL开始)

      1. 在数据模型的 XSD 中设置默认值(每种类型的“default”关键字)
      2. 使用插件的 cxf-xjc-dv 扩展来处理生成类的 getter 中的默认值。

      例如,这将为您的字段年龄创建一个吸气剂,如下所示:

      public Integer getAge() {
         if (age == null)
            return new Interger(0);
         return age;
      }
      

      【讨论】:

      • 这与 OP 想要的相反,因为这将返回 XML 中 not 指定的元素的默认值和元素的空字符串/空值 指定但有一个空值。 OP 想要指定但为空 -> 默认和未指定 -> null.
      猜你喜欢
      • 2019-04-11
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      • 1970-01-01
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多