xml - ejemplo - xstream maven
¿Cómo hacer que XStream omita las etiquetas no asignadas al analizar XML? (5)
Tengo un gran documento XML que quiero convertir a un bean Java. Tiene muchas etiquetas y atributos, pero solo me interesan unos cuantos. Desafortunadamente, parece que XStream lo obliga a declarar una propiedad en ese bean para cada etiqueta que pueda haber en ese XML. ¿Hay alguna forma de evitar esto?
He estado return this.realClass(fieldName) != null;
este problema hoy y lo que descubrí es que al usar return this.realClass(fieldName) != null;
No es (siempre) una solución operativa, sin embargo, en realidad hay una forma para que XStream omita etiquetas no asignadas Y trabaje con colecciones implícitas al mismo tiempo.
¿Por qué la realClass(fieldName)
no funciona?
De hecho truco con el uso
try {
return this.realClass(fieldName) != null;
} catch (Throwable t) {
return false;
}
trabajos. Lo que hace es intentar adivinar el tipo por el nombre de la etiqueta, ver si tuvo éxito y si no, devuelve falso. Así que perfectamente saltará etiquetas como
<someUnknownTag>someContent</someUnknownTag>
PERO funcionará solo hasta el momento (!) Cuando, de alguna manera, alguna etiqueta "no necesaria" tendrá un nombre significativo para el cual realClass(fieldName)
podrá devolver algo que no sea null
y esa etiqueta no ser miembro de cualquier colección implícita de la suya. En ese caso, sabiendo que la clase para un elemento xml podría definirse y que no existe un campo similar en los usuarios, el tipo XStream decidirá que "tal vez este elemento sea de alguna colección implícita". Y fallará muy pronto si no hay tal colección ni un campo en su clase. En mi caso la pieza problemática de xml fue así:
<url>http://somewhere.com</url>
y, por supuesto, no había Url url;
ni @XStreamImplicit List<Url> url
en mi clase. El resultado de tener un XML de este tipo y usar la cosa "realClass" es el siguiente:
com.thoughtworks.xstream.converters.ConversionException: Element url of type java.net.URL is not defined as field in type org.sample.xstream.SomeBean
La manera correcta
La forma correcta sería devolver simplemente false
desde shouldSerializeMember
en el caso cuando se definedIn == Object.class
(sin usar realClass(fieldName)
).
Pero solo usar el return false
solo no es suficiente. De esta forma, XStream dejará las colecciones implícitas vacías.
El truco aquí es asegurarse de que uno use @XStreamImplicit(itemFieldName = "something")
lugar de usar @XStreamImplicit
sin parámetros, incluso en los casos en que el nombre de etiqueta y el tipo de parámetro genérico de la colección tienen el mismo nombre.
Así que el código correcto se verá así:
xstream = new XStream() {
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
@Override
public boolean shouldSerializeMember(Class definedIn, String fieldName) {
if (definedIn == Object.class) {
//This is not compatible with implicit collections where item name is not defined
return false;
} else {
return super.shouldSerializeMember(definedIn, fieldName);
}
}
};
}
};
xsteam.processAnnotations(SomeRootEntry.class);
Y debe asegurarse de que en sus clases sus colecciones implícitas estén marcadas así:
@XStreamImplicit(itemFieldName = "something")
private List <Something> somethingList;
Observe que itemFieldName
se especifica explícitamente aunque el parámetro de tipo genérico de la Lista tiene el mismo nombre. Esto es crucial.
En este caso, al encontrar la etiqueta <something>
XStream ni siquiera visitará su shouldSerializeMember
con ese fieldName. Sólo sabrá de antemano que el elemento es de colecciones implícitas.
Cuando visite su método, se encontrará con <url>http://somewhere.com</url>
nuevamente. Pero aquí estamos a salvo ya que simplemente devolvemos false
.
¡Funciona para mi! Darle una oportunidad.
Use el método ignoreUnknownElements () en su instancia de XStream:
XStream xstream = new XStream();
xstream.ignoreUnknownElements();
XStream 1.4.5 te hace fácil tratar con etiquetas desconocidas. Utilice ignoreUnknownElements()
para las etiquetas que aún no están implementadas o que se eliminaron, y está tratando con un xml antiguo. También puede especificar qué etiqueta en particular le gustaría ignorar.
Ya que XStream 1.4.5 durante la declaración de marshaller es suficiente usar el método ignoreEnknownElements ():
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.getXStream().ignoreUnknownElements();
...
Ignorar elementos innecesarios.
Inicialice XStream
como se muestra a continuación para ignorar los campos que no están definidos en su bean.
XStream xstream = new XStream() {
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
@Override
public boolean shouldSerializeMember(Class definedIn, String fieldName) {
if (definedIn == Object.class) {
return false;
}
return super.shouldSerializeMember(definedIn, fieldName);
}
};
}
};