EclipseLink MOXy JSON Provider提供ClassCastException

时间:2016-01-10 00:20:48

标签: json classcastexception moxy

我需要编写代码来处理带有JSON消息体的REST请求,如下所示。

[
  {
    "name": "Foo",
    "description": "An entity"
  },
  {
    "name": "Bar",
    "description": "Another entity"
  }
]

这是下面类的JSON数组,要序列化。处理请求路径(使用@Path注释)的方法采用数组参数。方法签名是:public Response update(MyClass[] objects)

@XmlRootElement
public class MyClass {

    @XmlAttribute
    String name;

    @XmlAttribute
    String description;

    // getters & setters
}

我在服务器上使用带有MOXyJsonProvider的Jersey 2.6(注册了MoxyJsonFeature)但是我得到了ClassCastException:

java.lang.ClassCastException: MyClass cannot be cast to javax.xml.bind.JAXBElement
    org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.readFrom(MOXyJsonProvider.java:598)
    org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:251)
    ....

许多帖子中的建议修复是将@XmlRootElement注释添加到类中,但我已经有了。有人可以帮我搞定吗?非常感谢。

编辑:附加其他信息,以防万一。

逐步执行发生异常的代码,我看到,在org.eclipse.persistence.jaxb.rs.MOXyJsonProvider::readFrom方法中,unmarshaller.unmarshal(....)调用(下面的代码提取中的第一行)返回一个JAXBElement对象value字段为ArrayList,其中包含我想要的2个MyClass个实例。下一行的if - 条件求值为false,因此执行进入else子句。由于jaxbElement.getValue()ArrayList,因此会将其转换为ArrayList<JAXBElement>。最终,它会在下面的摘录末尾进入for循环,并在getValue()中的每个项目上调用arrayList,期望每个项目都是JAXBElement。但是列表中的实际项目是MyClass个实例,并且第一个项目上的getValue()调用会抛出ClassCastException

我怀疑修复程序会在MyClass定义中的注释中发生一些变化。

       ....
        JAXBElement<?> jaxbElement = unmarshaller.unmarshal(jsonSource, domainClass);
        if(type.isAssignableFrom(JAXBElement.class)) {
            return jaxbElement;
        } else {
            Object value = jaxbElement.getValue();
            if(value instanceof ArrayList) {
                if(type.isArray()) {
                    ArrayList<JAXBElement> arrayList = (ArrayList<JAXBElement>) value;
                    int arrayListSize = arrayList.size();
                    Object array;
                    if(genericType instanceof GenericArrayType) {
                        array = Array.newInstance(JAXBElement.class, arrayListSize);
                        for(int x=0; x<arrayListSize; x++) {
                            Array.set(array, x, arrayList.get(x));
                        }
                    } else {
                        array = Array.newInstance(domainClass, arrayListSize);
                        for(int x=0; x<arrayListSize; x++) {
                            Array.set(array, x, arrayList.get(x).getValue());
                        // ^^^^^^^ In the above line, arrayList.get(x) is a
                        //  MyClass instance. It is not a JAXBElement
                        }
                    }
          ....

1 个答案:

答案 0 :(得分:0)

我从以下方法更改了方法签名后,它正在运行:

public Response update(MyClass[] objects)

为:

public Response update(List<MyClass> objects)

一位同事告诉我试试。希望我早点问他。 :(

所以这解决了我的问题,但我不知道MyClass中的某些不同的注释是否会使它工作并产生数组而不是列表;或者如果这是MOXyJsonProvider中的错误;或者是否需要自定义代码才能使其与数组类型参数一起使用。