简体   繁体   English

在没有默认POJO构造函数的情况下将POJO转换为XML

[英]Converting POJO into XML without default POJO constructor

I'm trying to convert a POJO (Plain old Java Object) into XML using java.beans.XMLEncoder. 我正在尝试使用java.beans.XMLEncoder将POJO(普通旧Java对象)转换为XML。 My code works fine but I found one interesting problem that occurs when I omit the default constructor in my POJO. 我的代码工作正常,但我发现当我省略POJO中的默认构造函数时会出现一个有趣的问题。 Classes are below. 课程如下。

POJO without default constructor 没有默认构造函数的POJO

public class NFLTeam implements Serializable {

  private String name;
  private String description;

  // public NFLTeam() {
  //
  // }

  public NFLTeam(String name, String description) {
    this.name = name;
    this.description = description;
  }

  public String getName() {
        return name;
    }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

}

Invocation of XMLEncoder 调用XMLEncoder

public static void main(String args[]) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    XMLEncoder xmlEncoder = new XMLEncoder(byteArrayOutputStream);
    NFLTeam team = new NFLTeam("Bears", "Play for Chicago");
    xmlEncoder.writeObject(team);
    xmlEncoder.close();
    System.out.println(byteArrayOutputStream);
}

Console output with default constructor omitted 省略了默认构造函数的控制台输出

java.lang.InstantiationException: oce.wsd.pojos.NFLTeam
Continuing ...
java.lang.Exception: XMLEncoder: discarding statement XMLEncoder.writeObject(NFLTeam);
Continuing ...
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_45" class="java.beans.XMLDecoder">
</java>

Console output with default constructor 控制台输出使用默认构造函数

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_45" class="java.beans.XMLDecoder">
<object class="oce.wsd.pojos.NFLTeam">
    <void property="description">
      <string>Play for Chicago</string>
    </void>
    <void property="name">
     <string>Bears</string>
   </void>
</object>
</java>

I was googling around but cannot find any explanation for this. 我正在谷歌搜索,但无法找到任何解释。 Why is the implicit default constructor not enough for XMLEncoder? 为什么隐式默认构造函数对XMLEncoder不够?

Unfortunately JAXB (and linked technologies) requires a non-arg constructor (implicit default constructor is fine as well). 不幸的是,JAXB(和链接技术)需要一个非arg构造函数(隐式默认构造函数也可以)。

According to the specification and in case of native Oracle JAX library it is required for both marshaling and un-marshaling. 根据规范和原生Oracle JAX库的情况,编组和取消编组都需要它。

According to the human logic it is not needed for marshaling/serialization. 根据人类逻辑,编组/序列化不需要它。 For example the most popular JSON library Jackson does have such a requirement only for de-serialization. 例如,最流行的JSON库杰克逊确实只对反序列化有这样的要求。

There are third party XML JAX compatible parsers which are less restrictive as well... but this issue is usually not a reason for struggling with a third party library. 还有第三方XML JAX兼容解析器,限制性较低......但这个问题通常不是与第三方库挣扎的原因。

JAX allows to have a non-argument constructor non-public. JAX允许非参数构造函数非公共。 I usually create it as follow: 我通常创建它如下:

/** For JAXB only. Do not call directly and do not delete! */
@Deprecated
protected NFLTeam () {
    // nothing
}

From http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 : 来自http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9

If a class contains no constructor declarations, then a default constructor with no formal parameters and no throws clause is implicitly declared. 如果类不包含构造函数声明,则隐式声明没有形式参数且没有throws子句的默认构造函数。

In other words, a nullary constructor is implicit iff there is no other n-arg constructor. 换句话说,如果没有其他n-arg构造函数,则隐式构造函数是隐式的。 Try it yourself: 亲自尝试一下:

public class Main {

    public Main(int i) {

    }

    public static void main(String[] args) {
        new Main(); // error: the constructor Main() is undefined
    }

}

If you cannot, XMLEncoder neither. 如果你不能,XMLEncoder也不行。

I found the answer I was looking for here . 我找到了我在这里寻找的答案。 "The XMLEncoder class is a complementary alternative to the ObjectOutputStream and can be used to generate a textual representation of a JavaBean ". “XMLEncoder类是ObjectOutputStream的补充替代,可用于生成JavaBean的文本表示”。 JavaBean is the key here. JavaBean是这里的关键。 In order for the NFLTeam bean in the posted example to be considered a JavaBean , it needs the default constructor as mentioned here . 为了将发布的示例中的NFLTeam bean视为JavaBean ,它需要此处提到的默认构造函数。 "The class must have a public default constructor (with no arguments). This allows easy instantiation within editing and activation frameworks." “该类必须有一个公共默认构造函数(没有参数)。这样可以在编辑和激活框架中轻松实例化。”

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

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