1

我正在努力解决 marshal/unmarshall JSon 的几个问题,看起来我永远不会让它工作:(

看第一个问题:我有一个包含几个字段的类响应:字符串错误、字符串错误代码和对象响应。负责填写所有响应数据的类,如果需要填写错误字段并将其发送回客户端以进行进一步分析。

“对象响应”可以是任何类型(为什么是对象?因为它不适用于接口,这将是问题的第二部分)

代码片段:

   @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Response
    {
        public static final String ERROR_FIELD_NAME = "error";
        public static final String ERROR_CODE_FIELD_NAME = "error_code";
        public static final String RESPONSE_FIELD_NAME = "response";

        @XmlElement(name = Response.ERROR_CODE_FIELD_NAME)
        private String errorCode;

        @XmlElement(name = Response.ERROR_FIELD_NAME)
        private String errorMessage;

        @XmlElementRefs(
            {@XmlElementRef(type = AClassResponse.class),
        @XmlElementRef(type = BClassResponse.class)})
        private Object entity;

等等...

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;


//@XmlRootElement(name = Response.RESPONSE_FIELD_NAME)
//@XmlJavaTypeAdapter(AClassResponse.Adapter.class)
@XmlRootElement
public class AClassResponse
{
    private TargetObject target;


    public TargetObject getTarget()
    {
        return target;
    }


    public void setTarget(TargetObject target)
    {
        this.target = target;
    }
}

JSON 1 (for XmlElementRef AClassResponse.class ):
    { 
      "error" : "",
      "error_code" : "",
      **"aClassResponse" :** 
         { "target" : 
            { "accountId" : "5bd0812b",
              "id" : "6ccb6ae1-30c3-4aa0-8d1e-6ed61b6bb217",
              "isCaseSensitive" : "false",
              "maxNumberOfConnections" : "0",
              "name" : "targetName",
              "pathDelimiter" : "/",
              "type" : "SMB"
            } 
         }
    }

JSON 1 (for XmlElementRef BClassResponse.class):
   { 
      "error" : "",
      "error_code" : "",
      **"bClassResponse" :** 
         { "target" : 
            { "accountId" : "5bd0812b",
              "id" : "6ccb6ae1-30c3-4aa0-8d1e-6ed61b6bb217",
              "isCaseSensitive" : "false",
              "maxNumberOfConnections" : "0",
              "name" : "targetName",
              "pathDelimiter" : "/",
              "type" : "SMB"
            } 
         }
    }

现在的问题:

看看上面的 JSon,“aClassResponse”:“bClassResponse”:总是动态的(意味着名称是从类名派生的)——这不是我需要的。

我的目标是给这个名字一个持久的名字"response",这样任何远程客户端都会意识到这一点并依赖这个名字。

我知道,要解决这个问题,我可以用@XmlRootElement(name = "response")注释AClassResponse.class,并且它确实有效,直到您定义了多个 @XmlElementRef。

如果两个或更多,这会导致编组/取消编组出现问题,并且 JAXB 不知道绑定哪个类应该绑定到实体字段,因为它也依赖于名称(名称 =“响应”)

@XmlElementRefs(
        {@XmlElementRef(type = AClassResponse.class),
        @XmlElementRef(type = BClassResponse.class)})
        private Object entity;

它像这样对待它:

@XmlElementRefs(
            {@XmlElementRef(name = "response", type = AClassResponse.class),
            @XmlElementRef(name = "response", type = BClassResponse.class)})
            private Object entity;

假设这是一个正确的行为,我无法为任何对象类型保持相同(名称 =“响应”)。

好的,我尝试通过为每个实现引入接口而不是对象类型 + @XmlJavaTypeAdapter(AClassResponse.Adapter.class) 来解决它 - 但是它也没有工作,抛出不支持接口的异常等等......

这篇文章似乎可以对此有所了解,http://jaxb.java.net/guide/Mapping_interfaces.html

但它也失败了,说它不能实例化抽象类abstract class AbstractFooImpl

@XmlJavaTypeAdapter(AbstractFooImpl.Adapter.class)
interface IFoo {
  ...
}
**abstract class AbstractFooImpl implements IFoo {**
  ...

  static class Adapter extends XmlAdapter<AbstractFooImpl,IFoo> {
    IFoo unmarshal(AbstractFooImpl v) { return v; }
    AbstractFooImpl marshal(IFoo v) { return (AbstractFooImpl)v; }
  }
}

class SomeFooImpl extends AbstractFooImpl {
  @XmlAttribute String name;
  ...
}

class AnotherFooImpl extends AbstractFooImpl {
  @XmlAttribute int id;
  ...
}

class Somewhere {
  public IFoo lhs;
  public IFoo rhs;
}

关于我如何解决这个问题的任何建议?请帮忙..

谢谢你。

4

2 回答 2

0

您可以使用@XmlElements注释并执行以下操作:

@XmlElements({
    @XmlElementRef(name = "response", type = AClassResponse.class),
    @XmlElementRef(name = "response", type = BClassResponse.class)
})
private Object entity;
于 2012-06-29T01:51:09.130 回答
0

JAXB 不做接口。解决方案是泛型或抽象类(使用 @XmlTransient 注释以使 JAXB 忽略基类并使用 @XmlSeeAlso 使其使用特定实现)。这解决了 Java 部分,但您仍然需要修复等式的 XSD 部分(请记住,JAXB 只能通过 Jersey 看到您的 JSON 的 XML 版本)。

为此,您可以在字段上使用 @XmlElementRef 和 @XmlElementRefs 注释,以便 XSD 映射到特定实现的选择。

@XmlTransient // JAXB doesn't like abstract types, so do not map this type name
// XmlSeeAlso only required if BaseImpl/BaseImpl2 are not otherwise auto-discovered by JAXB
@XmlSeeAlso({BaseImpl.class, BaseImpl2.class })
public abstract class Base {
  @XmlElement(name='still-works')
  public String thisFieldWillStillBeMappedByJAXB;
}

@XmlRootElement("base-impl")
public class BaseImpl {}

@XmlRootElement("alternative")
public class BaseImpl2 {}

public class Complex<E extends Base> {
   @XmlElementRefs({
     @XmlElementRef(type=BaseImpl.class), 
     @XmlElementRef(type=BaseImpl2.class)
   })
   public E impl; // will be an instance of either "base-impl" or "alternative"
}
于 2012-06-29T01:59:42.823 回答