Springfox Swagger ignores #XmlElement for nested objects only - java

I'm using springfox 3.0.0 and my XML Swagger looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Foo>
<anotherBar>
<MyStr>string</MyStr>
</anotherBar>
<bar>
<MyStr>string</MyStr>
</bar>
<MyDate>2021-10-08T16:08:57.795Z</MyDate>
</Foo>
Here is what I would like:
<?xml version="1.0" encoding="UTF-8"?>
<Foo>
<AnotherBar>
<MyStr>string</MyStr>
</AnotherBar>
<Bar>
<MyStr>string</MyStr>
</Bar>
<MyDate>2021-10-08T16:08:57.795Z</MyDate>
</Foo>
As you can see, MyStr and MyDate are displayed correctly in the XML but not bar and anotherBar without the uppercase.
I don't know why the #XmlElement annotation is ignored by Springfox for nested objects only. But it works great with String or Instant.
Here is my Foo class:
#XmlRootElement(name = "Foo")
public class Foo {
#XmlElement(name = "MyDate")
private Instant myDate;
#XmlElement(name = "Bar")
private Bar bar;
#XmlElement(name = "AnotherBar")
private Bar anotherBar;
// Getter / Setter...
}
And here is my Bar class:
public class Bar {
#XmlElement(name = "MyStr")
private String myStr;
// Getter / Setter ...
}
Here is my XmlMapper config:
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new JaxbAnnotationModule());
I already tried to replace #XmlElement with #JacksonXmlProperty but it's the same result.
I found also this answer https://stackoverflow.com/a/64562167 but I don't want to use #JsonProperty since I need the JSON from Swagger to use attributes name.
Do you know why #XmlElement is ignored by Springfox in this case only?

Related

JAXB: how to unmarshal a List of objects of different types inside a wrapper?

I'm stucked at parsing the following xml with JAXB:
<?xml version="1.0" encoding="utf-8"?>
<dashboardreport name="exampleDashboard" version="6.5.6.1013" reportdate="2016-12-16T11:05:19.329+01:00" description="">
<data>
<incidentchartdashlet name="Incident Chart" description="" />
<chartdashlet name="WebRequestTime" showabsolutevalues="false" />
<chartdashlet name="WebServiceTime" showabsolutevalues="false" />
</data>
</dashboardreport>
I used the following java classes to unmarshal the xml:
Dashboardreport.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "dashboardreport")
public class Dashboardreport {
#XmlElementWrapper(name = "data")
#XmlElement(name = "chartdashlet")
protected List<Chartdashlet> chartdashlets;
#XmlElementWrapper(name = "data")
#XmlElement(name = "incidentchartdashlet")
protected List<Incidentchartdashlet> incidentchartdashlets;
#XmlAttribute(name = "name")
protected String name;
}
I just want to unmarshal the xml without using a wrapper class around incidentchartdashlets and chartdashlet, cause both types differ a lot.
I only can use the XmlElementWrapper annotation once, so that only chartdashlets get filled and incidentchartdashlets is null.
Is there any solution with JAXB without using a seperate wrapper class?
I assume your dashlet classes are defined like
class Chartdashlet extends Dashlet and class Incidentchartdashlet extends Dashlet.
Then the preferred JAXB way to handle your mixed list of dashlets would be
by using the #XmlElements
annotation:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "dashboardreport")
public class Dashboardreport {
#XmlElementWrapper(name = "data")
#XmlElements({
#XmlElement(name = "chartdashlet", type = Chartdashlet.class),
#XmlElement(name = "incidentchartdashlet", type = Incidentchartdashlet.class)
})
protected List<Dashlet> dashlets;
#XmlAttribute(name = "name")
protected String name;
}

Multiple XML tag by JAXB

I'm using JAXB for generating XML, like this:
<Country>
<City>..</City>
<Adr>...</Adr>
</Country>
I have special class, which generate this XML:
#XmlElement(name = "Country")
private String country;
#XmlElement(name = "City")
private String city;
#XmlElement(name = "Adr")
private String adr;
with setters and getters, of course. But, how need I change this code, if I want to see XML like this?
<Country>
<City>..</City>
<Adr>...</Adr>
<City>..</City>
<Adr>...</Adr>
</Country>

Hibernate Annotation on parent fields

I have a class that is a POJO with no special Hibernate annotations or information, like so:
public class Parent{
Long id;
String foo;
String bar;
/* ... getters and setters, toString(), etc... */
}
I would like to create a child class that has the Hibernate annotations on it. The idea is that the first class will not have any dependencies on it, and the second will have all of the JPA/Hibernate specific stuff. How can I do that without re-creating all the fields in the parent? I would like to put Hibernate annotations on the class
#Entity
public class PersistentChild extends Parent{
// ????
}
You can use the #MappedSuperclass annotation on the POJO, then add the other annotations, as it were a normal JPA entity. But in this case, the annotations will only affect the entity classes, which are inheriting from it. Example:
#MappedSuperclass
public class Parent implements Serializable {
#Id
Long id;
#Column(name = "foo", required = true)
String foo;
#Column(name = "bar", required = false)
String bar;
/* ... getters and setters, toString(), etc... */
}
If you really do not want to modify the superclass, you can use a mapping file:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
<mapped-superclass class="Parent">
<!-- add your mapping here -->
</mapped-superclass>
</entity-mappings>
Alternative approach
Also, you can just add the #MappedSuperclass annotation, then define all properties like this:
#Entity
#AttributeOverrides({
#AttributeOverride(name = "foo", column=#Column(name = "foo", required = true)),
#AttributeOverride(name = "bar", column=#Column(name = "bar", required = false))
})
public class PersistentChild extends Parent {
#Id #GeneratedValue
Long id;
}
If you want to externalize the mapping you have to use xml-mapping file.

JAXB Element Wrapper for a Single Group of Elements When Marshalling

I wish to have an XML structure like this:
<?xml version="1.0" encoding="UTF-8"?>
<MSG>
<CASE>
<Field1></Field1>
<Field2></Field2>
</CASE>
</MSG>
The problem is, with the #XmlElementWrapper, I need a collection of items but there will be only 1 case item. How can I have multiple root elements, for a single collection of elements? Preferably in a single class.
I want something like this, but it throws an exception.
#XmlRootElement( name="MSG")
public class XMLStructure {
#XmlElementWrapper(name="CASE")
#XmlElement(name = "Field1")
private String field1;
#XmlElementWrapper(name="CASE")
#XmlElement(name = "Field2")
private String field2;
}
In the EclipseLink MOXy implementation of JAXB (JSR-222) we have an #XmlPath extension that enables you to map this as:
#XmlRootElement( name="MSG")
#XmlAccessorType(XmlAccessType.FIELD)
public class XMLStructure {
#XmlPath("CASE/Field1/text()")
private String field1;
#XmlPath("CASE/Field2/text()")
private String field2;
}
For More Information
I have written more about the #XmlPath extension on my blog:
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html

Serialize Java List to XML using Jackson XML mapper

Hi I need to create an XML from JAVA using Jackson-dataformat XMLMapper.
The XML should be like
<Customer>
<id>1</id>
<name>Mighty Pulpo</name>
<addresses>
<city>austin</city>
<state>TX</state>
</addresses>
<addresses>
<city>Hong Kong</city>
<state>Hong Kong</state>
</addresses>
</Customer>
But I get it always like with an extra "< addresses> < /addresses>" tag.
<Customer>
<id>1</id>
<name>Mighty Pulpo</name>
<addresses>
<addresses>
<city>austin</city>
<state>TX</state>
</addresses>
<addresses>
<city>Hong Kong</city>
<state>Hong Kong</state>
</addresses>
<addresses>
</Customer>
I am using below code to create XML
JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();
XmlMapper mapper = new XmlMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.registerModule(jaxbAnnotationModule);
mapper.registerModule(new GuavaModule());
String xml = mapper.writeValueAsString(customer);
System.out.println(xml);
Please can some one help me? How can I remove the extra tag please. I have tried to use #XmlElement but it does not help help. TIA!!
Try the below code
#JacksonXmlRootElement(localName = "customer")
class Customer {
#JacksonXmlProperty(localName = "id")
private int id;
#JacksonXmlProperty(localName = "name")
private String name;
#JacksonXmlProperty(localName = "addresses")
#JacksonXmlElementWrapper(useWrapping = false)
private Address[] address;
// you can add it on getter method instead of declaration.
#JacksonXmlElementWrapper(useWrapping = false)
public Address[] getAddress(){
return address;
}
//getters, setters, toString
}
class Address {
#JacksonXmlProperty(localName = "city")
private String city;
#JacksonXmlProperty(localName = "state")
private String state;
// getter/setter
}
This setting changes default wrapping behavior, if you don't want to deal with annotation everywhere in your code.
XmlMapper mapper = new XmlMapper();
mapper.setDefaultUseWrapper(false);
Just to add to ManojP's answer, if adding the #JacksonXmlElementWrapper(useWrapping = false) on the declaration of your variable doesn't work (which was the case for me), adding it to the getter method will do the trick.

Categories

Resources