Подтвердить что ты не робот

Исключение класса Cast при попытке unmarshall xml?

Попытка пройти исключение класса из списка:

FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);

выбрасывает это исключение:

java.lang.ClassCastException: javax.xml.bind.JAXBElement

Я не понимаю этого - поскольку класс был сгенерирован с помощью инструмента xjc.bat - и классы, которые он сгенерировал, я не изменил вообще - так что здесь не должно быть проблем с кастингом. назад класс, который может быть передан в FooClass.

Любые идеи относительно того, что я делаю неправильно?

4b9b3361

Ответ 1

Есть ли FooClass аннотация XmlRootElement? Если нет, попробуйте:

Source source = new StreamSource(inputStream);
JAXBElement<FooClass> root = unmarshaller.unmarshal(source, FooClass.class);
FooClass foo = root.getValue();

Это основано на Неофициальном руководстве JAXB.

Ответ 2

Используйте JAXBIntrospector в JAXBElement, чтобы получить объект schemaObject, например →

JAXBContext jaxbContext = JAXBContext.newInstance(Class.forName(className));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object schemaObject = JAXBIntrospector.getValue(unmarshaller.unmarshal(new ByteArrayInputStream(xmlString.getBytes())));

Обратитесь: когда JAXB unmarshaller.unmarshal возвращает JAXBElement <MySchemaObject> или MySchemaObject?

Ответ 3

Сегодня я столкнулся с той же проблемой, увидел ответы здесь, сделал некоторые исследования и посмотрел на меня, что наиболее общим решением является использование JAXBIntrospector. Следовательно,

FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);

следует записать как

FooClass fooClass = (FooClass) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));

Или даже лучше, чтобы сделать его более общим -

T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));

Ответ 4

Для более полного объяснения прочитайте в этой статье. Оказывается, ваш XSD должен быть правильно настроен, т.е. Должен быть некоторый корневой элемент, охватывающий все остальные элементы.

XJC пытается поставить аннотацию @XmlRootElement на класс, который мы генерируем из сложного типа. Точное условие несколько уродливое, но основная идея заключается в том, что если мы можем статически гарантировать, что сложный тип не будет использоваться несколькими разными именами тегов, поместим @XmlRootElement.

Ответ 5

Я бы посмотрел на файл XML и убедился, что это примерно то, что вы ожидаете увидеть.

Я также временно изменил код на:

Object o = unmarshaller.unmarshal(inputStream);
System.out.println(o.getClass());

Если первый не удался, то класс-класс происходит внутри метода unmarshal, если он преуспеет, тогда вы можете увидеть фактический класс, который вы возвращаетесь, а затем выяснить, почему это не то, что вы ожидаете от него.

Ответ 6

Мы потратили слишком много часов на ловкость с классом JAXB factory, чтобы удовлетворить unmarshaller. Мы узнали, что использование unmarshaller без вызова JAXB-генерируемого объекта factory работает нормально. Надеюсь, что образец кода искушает кого-то разочарования:

System.out.println("Processing generic-type unmarshaller: ");
MessageClass mcObject = unmarshalXml(MessageClass.class, msgQryStreamSource,
    NAMESPACE + "." + "MessageClass");

public static <T> T unmarshalXml(Class<T> clazz, StreamSource queryResults,
    String contextNamespace)
    {
        T resultObject = null;
        try {
            //Create instance of the JAXBContext from the class-name
            JAXBContext jc;
            jc = JAXBContext.newInstance(Class.forName(clazz.getName()));
            Unmarshaller u = jc.createUnmarshaller();
            resultObject = clazz.cast(u.unmarshal(queryResults));
            }
              //Put your own error-handling here.
        catch(JAXBException e)
        {
            e.printStackTrace();
        }
        catch (ClassCastException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        return clazz.cast(resultObject);
    }

Ответ 7

Основываясь на предварительных ответах от коллег, на всякий случай все еще ищут ответ.

У меня возникла проблема определения корневого элемента моей схемы:

<schema>
  <element name="foo" type="bar" />
  <complexType name="bar" />
</schema>

И поэтому я получал исключение Cast:

try {            
        javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getPackage().getName());            
        javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
        File f = FileUtil.toFile(this.getPrimaryFile());            
        mobilityConfigType = (MobilityModelConfigType)unmarshaller.unmarshal(FileUtil.toFile(this.getPrimaryFile()));
    } catch (javax.xml.bind.JAXBException ex) {            
        java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
    }

Я сделал, чтобы изменить первую строку блока try на:

javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getName());

Это разрешило проблему для меня.

Ответ 8

Вы абсолютно уверены, что FooClass - это корневой элемент источника ввода xml, который вы передали? Unmarshall вернет объект корневого элемента, созданный xjc.

Ответ 9

Иногда у вас есть определение XSD с несколькими разными корневыми элементами (например, XSD, определенные в WSDL), и в этом случае у сгенерированных классов отсутствует @XmlRootElement. Так как пользователь mbrauh уже написал, вам нужно получить значение JAXBElement. В моем случае я использовал:

FooClass request = ((JAXBElement< FooClass >) marshaller.unmarshal(new StreamSource(classPathResource.getInputStream()))).getValue();

Таким образом, используя дженерики, вы можете легко избежать двойного литья.

Ответ 10

Задайте @XmlRootElement (name= "указатьName", namespace = "namespace" ) для преобразования объекта.

Ответ 11

Я также столкнулся с ошибкой "Javax.xml.bind.JAXBElement нельзя отбросить" и нашел это очень простое решение:

FooClass fooClass = (FooClass) ((JAXBElement) u.unmarshal(new File("xml/foo.xml")) ).getValue();

Так как, по-видимому, объект типа JAXBElement возвращается, вам нужно вместо этого вывести его значение.

Источник: https://forums.oracle.com/thread/1625944

Ответ 12

Попробуйте следующее:

JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement element = (JAXBElement) unmarshaller.unmarshal( new StringReader(xmlString));
Foo foo = (Foo)element;