Исключение класса Cast при попытке unmarshall xml?
Попытка пройти исключение класса из списка:
FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);
выбрасывает это исключение:
java.lang.ClassCastException: javax.xml.bind.JAXBElement
Я не понимаю этого - поскольку класс был сгенерирован с помощью инструмента xjc.bat - и классы, которые он сгенерировал, я не изменил вообще - так что здесь не должно быть проблем с кастингом. назад класс, который может быть передан в FooClass.
Любые идеи относительно того, что я делаю неправильно?
Ответы
Ответ 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;