2016-01-10 5 views
0

Мне нужно написать код для обработки запроса REST с помощью тела сообщения JSON, как показано ниже.EclipseLink MOXy JSON Провайдер, предоставляющий ClassCastException

[ 
    { 
    "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 
} 

Я использую Джерси 2.6 с MOXyJsonProvider на сервере (с 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 аннотация для класса, но у меня уже есть это. Может кто-то, пожалуйста, помогите мне заставить это работать? Большое спасибо.

EDIT: добавление дополнительной информации, если это помогает.

Пошаговый кода, где происходит исключение, я вижу, что в 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 
         } 
        } 
      .... 

ответ

0

Он работает в настоящее время после того, как я изменил метод подпись:

public Response update(MyClass[] objects) 

к:

public Response update(List<MyClass> objects) 

Коллега сказал мне, чтобы попробовать. Хотел бы я расспросить его раньше. :(

Итак, чтобы решить мою проблему, но я не знаю, получили бы какие-то разные аннотации в MyClass, и у вас получился массив вместо списка, или если это ошибка в MOXyJsonProvider; это настраиваемый код, необходимый для работы с аргументом типа массива.

Смежные вопросы