@@ -24,9 +24,8 @@ y esta otra ``Profesor``:
2424 :class: toggle
2525 :caption: Profesor.java
2626
27- .. caution :: Se ha definido el departamento como una cadena por simplificar el
28- código. En puridad, el departamento debería ser un Enum y, en ese caso,
29- habría que hacer :ref: `un traductor <json-jackson-no-primitivos >`.
27+ .. note :: Para no complicar en exceso el código se han puesto todos los
28+ atributos como :java-lang: `String `.
3029
3130.. _xml-jackson-write :
3231
@@ -78,20 +77,20 @@ respecto a |JSON|:
7877 + En |XML | el orden de los nodos elemento importa y podría ser que nos
7978 interesara predefinirlo.
8079
81- Teniendo presente esto, podemos alterar las clases anteriores del siguiente
82- modo :
80+ Teniendo presente esto, escribamos clases abstractas complementarias que
81+ incluyan las anotaciones y que luego mezclaremos :
8382
84- .. literalinclude :: files/Claustro-xml .java
83+ .. literalinclude :: files/ClaustroMixin .java
8584 :language: java
8685 :class: toggle
87- :caption: Claustro .java
88- :emphasize-lines: 1,4,7,8
86+ :caption: ClaustroMixin .java
87+ :emphasize-lines: 1,3,6,7
8988
90- .. literalinclude :: files/Profesor-xml .java
89+ .. literalinclude :: files/ProfesorMixin .java
9190 :language: java
9291 :class: toggle
93- :caption: Profesor .java
94- :emphasize-lines: 3
92+ :caption: ProfesorMixin .java
93+ :emphasize-lines: 2, 5, 8
9594
9695Hemos utilizados anotaciones sobre las clases para:
9796
@@ -130,6 +129,44 @@ Hemos utilizados anotaciones sobre las clases para:
130129 Por supuesto, la anotación también es válida cuando se genera el formato
131130 |JSON |, pero no suele tener importancia.
132131
132+ .. note :: En este ejemplo tenemos una clase explícita (``Claustro``) que sirve
133+ como envoltorio a una lista de profesores. Obśervese que es en este
134+ envoltorio donde controlamos qué etiquetas se utilizan para los elementos de
135+ la lista. En otro caso distinto en que
136+ tuviéramos solamente una lista (o array) y quisiéramos generar un |XML |,
137+ deberíamos ser conscientes de que en la traducción no podríamos controlar el
138+ elemento padre ni los nombres de las etiquetas de los elementos de la lista.
139+ Es decir, si tuviéramos una lista de objetos ``Profesor `` al generar un |XML |
140+ obtendríamos lo siguiente:
141+
142+ .. code-block :: xml
143+
144+ <Profesor >
145+ <Profesor >
146+ <!-- Contenido del primer profesor... -->
147+ </Profesor >
148+
149+ <!-- Más profesores -->
150+ </Profesor >
151+
152+ Si nuestra intención fuera controlar los nombres de esas etiquetas al
153+ traducir a XML, entonces tendríamos que crear una clase adicional que hiciera
154+ de envoltorio, aunque en nuestro modelo de datos no exista:
155+
156+ .. code-block :: java
157+
158+ @JsonRootName (value = " claustro" )
159+ public class ProfesorWrapper {
160+
161+ @JacksonXmlElementWrapper (useWrapping = false )
162+ @JacksonnXmlProperty (localName = " profesor" )
163+ private Profesor [] profesores;
164+ }
165+
166+ Por supuesto, antes de escribir el |XML | deberíamos crear un objeto de este
167+ clase envoltorio y asignar al atributo ``profesores `` la lista de profesores
168+ existente.
169+
133170Por último queda generar la salida en el programa principal, que es básicamente
134171igual que :ref: `la escritura en el caso de JSON <json-jackson-write >`:
135172
@@ -145,18 +182,24 @@ igual que :ref:`la escritura en el caso de JSON <json-jackson-write>`:
145182 }
146183 );
147184
148- ObjectMapper mapper = new XmlMapper ()
149- .configure(ToXmlGenerator . Feature . WRITE_XML_DECLARATION , true )
150- .enable(SerializationFeature . INDENT_OUTPUT ); // Salida "bonita".
185+ XmlFactory factory = XmLFactory . builder()
186+ .enable(XmlWriteFeature . WRITE_XML_DECLARATION )
187+ .enable(XmlWriteFeature . WRITE_XML_1_1 )
188+ .build();
189+
190+ MapperBuilder<?, ?> builder = XmlFactory . builder(factory)
191+ .enable(SerializationFeature . INDENT_OUTPUT )
192+ .addMixIn(Claustro . class, ClaustroMixin . class)
193+ .addMixIn(Profesor . class, ProfesorMixin . class);
194+
195+ ObjectMapper mapper = builder. build();
151196
152197 try (
153198 OutputStream st = Files . newOutputStream(archivo);
154199 OutputStreamWriter sw = new OutputStreamWriter (st);
155- )
156- {
200+ ) {
157201 mapper. writeValue(sw, claustro);
158- }
159- catch (IOException err) {
202+ } catch (IOException err) {
160203 err. printStackTrace();
161204 }
162205
@@ -168,8 +211,7 @@ También podríamos haber generado una cadena con la salida:
168211 try {
169212 String contenido = mapper. writeValueAsString(claustro);
170213 System . out. println(contenido);
171- }
172- catch (IOException err) {
214+ } catch (IOException err) {
173215 err. printStackTrace();
174216 }
175217
@@ -189,19 +231,22 @@ Habiendo definido las clases con anotaciones como en el apartado anterior, la
189231lectura del formato es :ref: `prácticamente la misma que para JSON <json-jackson-read >`:
190232
191233.. code-block :: java
192- : emphasize- lines: 2
193234
194235 Path archivo = Path . of(System . getProperty(" user.home" ), " claustro.xml" );
195- ObjectMapper mapper = new XmlMapper ();
236+
237+ MapperBuilder<?, ?> builder = XmlFactory . builder()
238+ .addMixIn(Claustro . class, ClaustroMixin . class)
239+ .addMixIn(Profesor . class, ProfesorMixin . class);
240+
241+ ObjectMapper mapper = builder. build();
196242
197243 try (
198244 InputStream st = Files . newInputStream(ruta);
199245 InputStreamReader sr = new InputStreamReader (st);
200246 ) {
201247 Claustro claustro = mapper. readValue(sr, Claustro . class);
202248 System . out. println(claustro);
203- }
204- catch (IOException err) {
249+ } catch (IOException err) {
205250 err. printStackTrace();
206251 }
207252
0 commit comments