我正在努力解决JSon的少数问题,并且看起来我永远不会让它发挥作用:(
查看第一个问题:我有一个包含几个字段的类Response:String error,String error_code和Object response。负责将所有数据填入响应的类,如果需要填写错误字段并将其发送回客户端以进行进一步的分析。
"对象响应"可以是任何类型(为什么对象?因为它没有使用接口,这将是问题的第二部分)
代码段
@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" :总是动态的(意思是名称来自类名) - 这不是我需要的。
我的目标是为此名称提供持久性名称"响应" ,以便任何远程客户端都能够了解此名称并依赖此名称。
我知道,为了解决这个问题,我可以使用 @XmlRootElement(名称="响应")注释 AClassResponse.class ,它确实可以正常工作你定义了多个@XmlElementRef。
如果两个或更多,这会导致封送/解组的问题,并且JAXB不知道要绑定的类应该绑定到实体字段,因为它也依赖于名称(name =&#34 ;响应&#34)
@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;
假设这是一个正确的行为,我无法为任何对象类型保持相同(name =" response")。
好的,我尝试通过为每个实现引入接口而不是Object类型+ @XmlJavaTypeAdapter(AClassResponse.Adapter.class)来解决它 - 但是它也没有工作,抛出异常,不支持接口和等...
这篇文章似乎可以阐明这一点,http://jaxb.java.net/guide/Mapping_interfaces.html
但它也失败了,说它不能实例化抽象类抽象类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;
}
有关我如何解决此问题的任何建议?请帮忙..
谢谢。答案 0 :(得分:0)
您可以使用@XmlElements
注释并执行以下操作:
@XmlElements({
@XmlElementRef(name = "response", type = AClassResponse.class),
@XmlElementRef(name = "response", type = BClassResponse.class)
})
private Object entity;
答案 1 :(得分: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"
}