Java - XML POJO - java

I'm trying to create an XMLElement Pojo that would then be converted to a string that would suffice:
result = "<layerA><layerB><itemA><someProperty>100.00</someProperty>......</layerA>
<layerA>
<layerB>
<itemA>
<someProperty>100.00</someProperty>
</itemA>
<itemB>
<differentProperty>AAA</differentProperty>
</itemB>
</layerB>
</layerA>
public class layerA
#XmlElement(required = true)
private LayerB layerB;
public class layerB
#XmlElement(required = true)
private LayerB layerB;
#XmlElement(required = true)
private List<Object> items; ?????????
There can be itemA, itemB, itemC, itemD etc --> in the xml they are classified via name itemA, itemB, and can have different properties.
Wondering if there's a quick way to construct that xml, ultimately it would be a string.

Related

How to unmarshal array or list using JAXB?

I have an XML file and I need to set it up with my POJO class
<ids xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" >
<a:string>100</a:string>
<a:string>101</a:string>
<a:string>102</a:string>
... etc..
</ids>
Which annotation do I have to use, to fetch these values
I am using the following way.
#XmlElement(name="string",namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays")
protected List<String> id;
but I am getting null
You did not present the class containing protected List<String> id. It should be something like
#XmlRootElement(name = "ids")
public class Wrapper {
#XmlElement(name = "string",
namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")
protected List<String> id;
}
to have the list populated. Also you can name the class Ids and remove name = 'Ids'.

How do I unmarshall a repeated XML tag having same name but different structure inside another XML tag using Jaxb or jackson

XML which I want to unmarshall to java object:
<API Name="A">
<Input>
<Shipment
EnterpriseCode="ABC"
SellerOrganizationCode="6528"
ShipNode=""
ShipmentKey="202105171041273117421546">
<ShipmentLines>
<ShipmentLine BackroomPickedQuantity="2.0"
ShipmentLineKey="41273117421545">
<Extn
ExtnStagingLocation="location1"/>
</ShipmentLine>
</ShipmentLines>
<Extn ExtnInPickupLocker="N"
ExtnPickerId="1531685"
ExtnPickingHasStartedFlag="Y"
ExtnStagedByUserName="Windows and Walls"
ExtnStagingLocation=""/>
</Shipment>
</Input>
</API>
Below is the EXTN and EXTN1 java classes which I trying to map with XML have used JAXB and JACKSON to identify and map the variables with EXTN tag to java class Extn and Extn1.
#XmlAccessorType(XmlAccessType.FIELD)
#Data
#ToString
#NoArgsConstructor
#AllArgsConstructor
public static class Extn {
#JsonProperty(value = "ExtnStagingLocation")
#JacksonXmlProperty(isAttribute = true)
private String extnStagingLocation = "location1";
#JsonProperty(value = "ExtnInPickupLocker")
#XmlAttribute(name = "ExtnInPickupLocker", required = true)
private String extnInPickupLocker = "N";
#JsonProperty(value = "ExtnPickerId")
#JacksonXmlProperty(isAttribute = true)
private String extnPickerId = "1531685";
#JsonProperty(value = "ExtnPickingHasStartedFlag")
#JacksonXmlProperty(isAttribute = true)
private String extnPickingHasStartedFlag = "Y";
#JsonProperty(value = "ExtnStagedByUserName")
#JacksonXmlProperty(isAttribute = true)
private String ExtnStagedByUserName = "Windows and Walls";
}
#XmlAccessorType(XmlAccessType.FIELD)
#Data
#ToString
#NoArgsConstructor
#AllArgsConstructor
public static class Extn1 {
#JsonProperty(value = "ExtnStagingLocation")
#JacksonXmlProperty(isAttribute = true)
private String extnStagingLocation = "location1";
}
How do I Create a single class EXTN and then pass the desired attributes at different level while creating java object, rather creating different java class Extn and Extn1 and map the attributes inside the Extn tag
Note: Have created EXTN and EXTN1 to pass different attribute and it's value at different place

Change tag name in SOAP xml response (field in class and tag in response must be different)

I have class like this:
#Root(name = "address_v1", strict = false)
public class AddressItem {
#Attribute(name = "idAddress")
private Long addressId;
#Attribute(name = "idClient")
private Long clientId;
...
}
And I have response:
...
<ax23:address xsi:type="ax24:AddressItem">
<ax24:addressId>1111</ax24:addressId>
<ax24:clientId>1109</ax24:clientId>
...
But I need:
<ax23:address xsi:type="ax24:AddressItem">
<ax24:idAddress>1111</ax24:idAddress>
<ax24:idClient>1109</ax24:idClient>
Annotation #Attribute(name = "idAddress") doesn't work. (org.simpleframework.xml.Attribute).
I use wsdl2java as wsdl creator.
try with following steps and modify your POJO class as given below,
use #Element annotation for XML Element instead of #Attribute annotation (please refer to documentation for more info)
The Element annotation is used to represent a field or method that
appears as an XML element.
set the relevant xml element names to #Root and #Element annotations
AddressItem.java
#Root(name = "ax23:address", strict = false)
public class AddressItem {
#Element(name = "ax24:addressId")
private Long addressId;
#Element(name = "ax24:clientId")
private Long clientId;
...
}

How do you deserialize XML without multiple wrapper classes?

I have some XML that I want to turn into an object using Jackson FasterXML. The XML looks like this:
<services>
<service id="1" name="test">
<addresses>
<postalAddress id="2" line1="123 Fake Street" city="Springfield" />
</addresses>
</service>
</services>
I am deserializing this as an object successfully with these classes:
JsonIgnoreProperties(ignoreUnknown = true)
#JacksonXmlRootElement(localName = "services")
public class ServiceWrapper {
#JacksonXmlProperty(localName = "service")
private Service service;
//Getters and setters [...]
}
#JsonIgnoreProperties(ignoreUnknown = true)
public class Service {
#JacksonXmlProperty(isAttribute = true)
private int id;
#JacksonXmlProperty(isAttribute = true)
private String name;
#JacksonXmlProperty(localName = "addresses")
private AddressWrapper addresses;
//Getters and setters [...]
}
public class AddressWrapper {
#JacksonXmlProperty(localName = "postalAddress")
private List<Address> addresses;
//Getters and setters [...]
}
#JsonIgnoreProperties(ignoreUnknown = true)
public class Address {
#JacksonXmlProperty(isAttribute = true, localName = "id")
private int id;
#JacksonXmlProperty(isAttribute = true, localName = "line1")
private int address1;
#JacksonXmlProperty(isAttribute = true, localName = "city")
private int city;
//Getters and setters [...]
}
And the code to do the mapping:
JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);
ObjectMapper mapper = new XmlMapper(module);
mapper.registerModule(new JSR310Module());
mapper.configure(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS, true);
ServiceWrapper serviceWrapper = mapper.readValue(xmlString, ServiceWrapper.class);
return serviceWrapper.getService();
This all works fine, but it's a lot of overhead and ugly code to have the ServiceWrapper and AddressWrapper classes; when really all I want is the data in the <service> node and <postalAddress> node. Is it possible to tell the Jackson object to directly populate a list of Addresses in my Service class without having the AddressWrapper class to represent the <addresses> node? Similarly to take the entire xml and populate a Service class directly without needing a ServiceWrapper class?
The normal way to avoid writing/maintaining such code is to use JAXB to generate the Java code (with appropriate annotations). This process uses an XML schema (.xsd) as the input, with an optional bindings file (.xjb) to customize the generated code.
It looks like many of the JAXB annotations are supported by Jackson.
I will also note that JAXB code generator (xjc) supports plugins that allow you to do pretty much anything you want to augment the generated code (e.g., with additional methods or annotations).

Map XML to Java with multiple option for tag names

I need to parse an XML file then map it to a Java object. So far, I do it with an annotated POJO :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {"title", "id", "eventList"})
#XmlRootElement(name = "MyClass")
public class MyClass {
#XmlElement(name = "Title", required = true)
protected String title;
#XmlElement(name = "Id", required = false)
protected String id;
#XmlElement(name = "EventList", required = true)
protected EventList eventList;
}
Then unmarshall it with JAXB :
MyClass myObj = (MyClass) unmarshaller.unmarshal(new StreamSource(fis))
Problem : Sometimes, my customer send files with slightly different tag names (for example, Eventlist instead of EventList)
Is there an option to allow both names for a tag? Up to now, I solve this problem by giving 2 attributes in the POJO :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {"title", "id", "eventList"})
#XmlRootElement(name = "MyClass")
public class MyClass {
#XmlElement(name = "Title", required = true)
protected String title;
#XmlElement(name = "Id", required = false)
protected String id;
#XmlElement(name = "EventList", required = false)
protected EventList eventList;
#XmlElement(name = "Eventlist", required = false)
protected EventList eventlist;
}
This is hard to maintain and forbids me to use the 'required' attribute. Do you have a better solution?
I am not sure there is an option to add multiple names, but what you can do is:
make the fields private and add getters and setters for them. You can make 2 getters and setters for the eventlist-field and annotate them with different names. Since this field is not required, as I see, there will be no problem.
Although.. as I see now, the problem is actually solved. See here: JAXB: unmarshalling xml with multiple names for the same element

Categories