Java xml serialization null handling - java

I am using JAXB2 to serialize object to xml.
Is there any way how to force it to create entire object structure like in following example even if it is not filled in backing object?
This is my intended result even without having asignee property set.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<note>
<to xsi:nil="true"/>
<from xsi:nil="true"/>
<header xsi:nil="true"/>
<body>text</body>
<assignee>
<name xsi:nil="true"/>
<surname xsi:nil="true"/>
</assignee>
</note>
I use following code for serialization:
JAXBContext jc = JAXBContext.newInstance(dataObject.getClass());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocation);
marshaller.setProperty(Marshaller.JAXB_ENCODING, charset);
marshaller.marshal(dataObject, outputStream);

You can do the following:
Note
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlRootElement
#XmlType(propOrder={"to", "from", "header", "body", "assignee"})
public class Note {
private String to;
private String from;
private String header;
private String body;
private Assignee assignee;
#XmlElement(nillable=true)
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
#XmlElement(nillable=true)
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
#XmlElement(nillable=true)
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
#XmlElement(nillable=true)
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Assignee getAssignee() {
return assignee;
}
public void setAssignee(Assignee assignee) {
this.assignee = assignee;
}
}
Assignee
We will need to have a means to no when an unmarshalled instance of Assignee should be interpreted as null. I have added an isNull() method that returns true if all the fields are null.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlJavaTypeAdapter(AssigneeAdapter.class)
public class Assignee {
private String name;
private String surname;
#XmlElement(nillable=true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement(nillable=true)
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public boolean isNull() {
return null == name && null == surname;
}
}
AssigneeAdapter
The AssigneeAdapter uses both the Assignee object for the value type and bound type. This class leverages the isNull() method we added on Assignee:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class AssigneeAdapter extends XmlAdapter<Assignee, Assignee> {
#Override
public Assignee unmarshal(Assignee v) throws Exception {
if(v.isNull()) {
return null;
}
return v;
}
#Override
public Assignee marshal(Assignee v) throws Exception {
if(null == v) {
return new Assignee();
}
return v;
}
}
Demo
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Note.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(new Note(), System.out);
}
}
For more information on XmlAdapter see:
http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
http://bdoughan.blogspot.com/2010/12/jaxb-and-immutable-objects.html

Yes. Use a combination of #XmlElementRef and JAXBElement with nil set to true.
See:
http://download.oracle.com/javase/6/docs/api/javax/xml/bind/JAXBElement.html
http://download.oracle.com/javaee/6/api/javax/xml/bind/annotation/XmlElementRef.html

Related

Specifying root and child nodes with JAXB

Staying within JAXB how would I refactor MyNote so that it conforms to:
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
Which is well formed but not valid, to my understanding. Current output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MyNotes>
<Note>
<note>XY3Z1RGEO9W79LALCS</note>
<to>LJAY9RNMUGGENGNND9</to>
<from>GOVSHVZ3GJWC864L7X</from>
<heading>EX6LGVE5LGY4A6B9SK</heading>
<body>L95WYQNMEU1MFDRBG4</body>
</Note>
</MyNotes>
which is too flat, rather than nested as the example.
I believe this makes note the root element, with other elements being children nodes to note if I'm using correct terminology.
The MyNote class:
package net.bounceme.dur.jaxb.hello.world;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlType(propOrder = {"note", "to", "from", "heading", "body"})
#XmlRootElement(name = "note")
public class MyNote {
private String note;
private String to;
private String from;
private String heading;
private String body;
public String getNote() {
return note;
}
#XmlElement(name = "note")
public void setNote(String note) {
this.note = note;
}
public String getTo() {
return to;
}
#XmlElement(name = "to")
public void setTo(String to) {
this.to = to;
}
public String getFrom() {
return from;
}
#XmlElement(name = "from")
public void setFrom(String from) {
this.from = from;
}
public String getHeading() {
return heading;
}
#XmlElement(name = "heading")
public void setHeading(String heading) {
this.heading = heading;
}
public String getBody() {
return body;
}
#XmlElement(name = "body")
public void setBody(String body) {
this.body = body;
}
#Override
public String toString() {
return note + to + from + heading + body;
}
}
The MyNotes class:
package net.bounceme.dur.jaxb.hello.world;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "MyNotes")
public class MyNotes {
private static final Logger LOG = Logger.getLogger(MyNotes.class.getName());
private List<MyNote> myNotes = new ArrayList<>();
public MyNotes() {
}
public List<MyNote> getMyNotes() {
LOG.info(myNotes.toString());
return myNotes;
}
#XmlElement(name = "Note")
public void setMyNotes(List<MyNote> myNotes) {
LOG.info(myNotes.toString());
this.myNotes = myNotes;
}
public void add(MyNote myNote) {
LOG.info(myNote.toString());
myNotes.add(myNote);
}
#Override
public String toString() {
StringBuffer str = new StringBuffer();
for (MyNote note : this.myNotes) {
str.append(note.toString());
}
return str.toString();
}
}
exercising the MyNote and MyNotes classes:
public MyNotes unmarshallMyNotesFromFile(URI uri) throws Exception {
File file = new File(uri);
JAXBContext jaxbContext = JAXBContext.newInstance(MyNotes.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
MyNotes myNotes = (MyNotes) jaxbUnmarshaller.unmarshal(file);
return myNotes;
}
public void marshallMyNotesAndWriteToFile(MyNotes notes, URI uri) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(MyNotes.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(notes, new File(uri));
jaxbMarshaller.marshal(notes, System.out);
}
I'm looking to grab this xml through the web; first need to match the structure to the example.
You are very close. You need to change how you name your xmlElement for myNotes in MyNotes class. Also MyNote should not have a note field itself (according to your desired xml). Your edited classes would look like this (I also removed the logging statements for my convenience):
#XmlType(propOrder = { "to", "from", "heading", "body"})
#XmlRootElement(name = "note")
public class MyNote {
private String to;
private String from;
private String heading;
private String body;
public String getTo() {
return to;
}
#XmlElement(name = "to")
public void setTo(String to) {
this.to = to;
}
public String getFrom() {
return from;
}
#XmlElement(name = "from")
public void setFrom(String from) {
this.from = from;
}
public String getHeading() {
return heading;
}
#XmlElement(name = "heading")
public void setHeading(String heading) {
this.heading = heading;
}
public String getBody() {
return body;
}
#XmlElement(name = "body")
public void setBody(String body) {
this.body = body;
}
#Override
public String toString() {
return to + from + heading + body;
}
}
and MyNotes:
#XmlRootElement(name = "MyNotes")
public class MyNotes {
private List<MyNote> myNotes = new ArrayList<>();
public MyNotes() {
}
public List<MyNote> getMyNotes() {
return myNotes;
}
#XmlElement(name = "note")
public void setMyNotes(List<MyNote> myNotes) {
this.myNotes = myNotes;
}
public void add(MyNote myNote) {
myNotes.add(myNote);
}
#Override
public String toString() {
StringBuffer str = new StringBuffer();
for (MyNote note : this.myNotes) {
str.append(note.toString());
}
return str.toString();
}
}

Not able to extract only selected Tag values using Jaxb in Java

I've a very big XML string. Im posting here only part of the XML object. I'm trying to convert this XML to Java object. My first question is, should I need to create Java object of total XML tag values or can I have create the Java object of only selected inner XML objects? Please find my XML string.
<DATAPACKET REQUEST-ID = "2">
<HEADER>
<RESPONSE-TYPE CODE="1" DESCRIPTION="Response DataPacket"/>
<SEARCH-RESULT-LIST>
<SEARCH-RESULT-ITEM>
<NAME MATCHED="TRUE"/>
</SEARCH-RESULT-ITEM>
</SEARCH-RESULT-LIST>
</HEADER>
<BODY>
<CONS_SCORE>
<SCORE>0</SCORE>
<REASON1>
<HEADER></HEADER>
<DESCRIPTION></DESCRIPTION>
</REASON1>
<REASON2>
<HEADER></HEADER>
<DESCRIPTION></DESCRIPTION>
</REASON2>
<REASON3>
<HEADER></HEADER>
<DESCRIPTION></DESCRIPTION>
</REASON3>
<REASON4>
<HEADER></HEADER>
<DESCRIPTION></DESCRIPTION>
</REASON4>
</CONS_SCORE>
<CONSUMER_PROFILE2>
<CONSUMER_DETAILS2>
<RUID>1234</RUID>
<NAME>ABC</NAME>
<DATE_OF_BIRTH>1980-03-03T00:00:00+03:00</DATE_OF_BIRTH>
<GENDER>001</GENDER>
</CONSUMER_DETAILS2>
<ID_DETAILS2>
<SLNO>1</SLNO>
<SOURCE_ID>001</SOURCE_ID>
<ID_VALUE>2806</ID_VALUE>
<EXP_DATE>2018-07-13T00:00:00+03:00</EXP_DATE>
</ID_DETAILS2>
</CONSUMER_PROFILE2>
</BODY>
</DATAPACKET>
In the above object, I want to fetch only CONSUMER_PROFILE2 object. Here is my Dto class
#XmlRootElement(name = "DATAPACKET")
public class ConsumerProfileDto {
private ConsumerDetailsDto CONSUMER_DETAILS2;
private IdDetailsDto ID_DETAILS2;
public ConsumerDetailsDto getCONSUMER_DETAILS2() {
return CONSUMER_DETAILS2;
}
public void setCONSUMER_DETAILS2(ConsumerDetailsDto cONSUMER_DETAILS2) {
CONSUMER_DETAILS2 = cONSUMER_DETAILS2;
}
public IdDetailsDto getID_DETAILS2() {
return ID_DETAILS2;
}
public void setID_DETAILS2(IdDetailsDto iD_DETAILS2) {
ID_DETAILS2 = iD_DETAILS2;
}
}
CONSUMER_DETAILS2 class
#XmlRootElement(name = "CONSUMER_DETAILS2")
public class ConsumerDetailsDto {
private String NAME;
private String DATE_OF_BIRTH;
private String GENDER;
private String NATIONALITY;
public String getNAME() {
return NAME;
}
public void setNAME(String nAME) {
NAME = nAME;
}
public String getDATE_OF_BIRTH() {
return DATE_OF_BIRTH;
}
public void setDATE_OF_BIRTH(String dATE_OF_BIRTH) {
DATE_OF_BIRTH = dATE_OF_BIRTH;
}
public String getGENDER() {
return GENDER;
}
public void setGENDER(String gENDER) {
GENDER = gENDER;
}
public String getNATIONALITY() {
return NATIONALITY;
}
public void setNATIONALITY(String nATIONALITY) {
NATIONALITY = nATIONALITY;
}
Here is the code of unmarshalling
JAXBContext jaxbContext = JAXBContext.newInstance(ConsumerProfileDto.class);
StringReader reader = new StringReader(responseXML);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
ConsumerDetailsDto que= (ConsumerDetailsDto) jaxbUnmarshaller.unmarshal(reader);
System.out.println(que.getDATE_OF_BIRTH());
System.out.println(que.getGENDER());;
System.out.println(que.getNAME());
P.S
I've used DocumentBuilder and I'm able to fetch the values using it. But, I want to extract using Jaxb.
You can't annotate as #XmlRootElement the Java class mirroring the XML element that you're interested on. You have to mirror in Java all the XML elements from the topmost element in the XML file (DATAPACKET) to the lowest ones (CONSUMER_DETAILS2 and ID_DETAILS2) in the path that you're interested, even if you're only interested in some of them.
I assume that the operator isn't interested in RUID (because the class CONSUMER_DETAILS2 doesn't include a field for this XML element), and also that the field NATIONALITY is not going to be loaded from this XML.
If the input XML of the question were in a file named input2.xml, then I'd have the following Java classes:
DataPacket
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.NONE)
#XmlRootElement(name = "DATAPACKET")
public class DataPacket {
#XmlAttribute(name = "REQUEST_ID")
private int REQUEST_ID;
#XmlElement(name ="BODY")
private Body BODY;
public DataPacket(){}
public int getREQUEST_ID() {
return REQUEST_ID;
}
public void setREQUEST_ID(int REQUEST_ID) {
this.REQUEST_ID = REQUEST_ID;
}
public Body getBODY() {
return BODY;
}
public void setBODY(Body BODY) {
this.BODY = BODY;
}
}
Body
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.NONE)
class Body {
#XmlElement(name = "CONSUMER_PROFILE2")
private ConsumerProfile profile;
public Body(){}
public ConsumerProfile getProfile() {
return profile;
}
public void setProfile(ConsumerProfile profile) {
this.profile = profile;
}
}
ConsumerProfile
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.NONE)
public class ConsumerProfile {
#XmlElement(name = "CONSUMER_DETAILS2")
private ConsumerDetails CONSUMER_DETAILS2;
#XmlElement(name = "ID_DETAILS2")
private IdDetails ID_DETAILS2;
public ConsumerProfile(){}
public ConsumerDetails getCONSUMER_DETAILS2() {
return CONSUMER_DETAILS2;
}
public void setCONSUMER_DETAILS2(ConsumerDetails cONSUMER_DETAILS2) {
CONSUMER_DETAILS2 = cONSUMER_DETAILS2;
}
public IdDetails getID_DETAILS2() {
return ID_DETAILS2;
}
public void setID_DETAILS2(IdDetails iD_DETAILS2) {
ID_DETAILS2 = iD_DETAILS2;
}
}
ConsumerDetails
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.NONE)
class ConsumerDetails {
#XmlElement(name="NAME")
private String NAME;
#XmlElement(name="DATE_OF_BIRTH")
private String DATE_OF_BIRTH;
#XmlElement(name="GENDER")
private String GENDER;
private String NATIONALITY;
public ConsumerDetails(){}
public String getNAME() {
return NAME;
}
public void setNAME(String nAME) {
NAME = nAME;
}
public String getDATE_OF_BIRTH() {
return DATE_OF_BIRTH;
}
public void setDATE_OF_BIRTH(String dATE_OF_BIRTH) {
DATE_OF_BIRTH = dATE_OF_BIRTH;
}
public String getGENDER() {
return GENDER;
}
public void setGENDER(String gENDER) {
GENDER = gENDER;
}
public String getNATIONALITY() {
return NATIONALITY;
}
public void setNATIONALITY(String nATIONALITY) {
NATIONALITY = nATIONALITY;
}
}
IdDetails
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.NONE)
class IdDetails {
#XmlElement(name="SLNO")
private int SLNO;
#XmlElement(name="SOURCE_ID")
private String SOURCE_ID;
#XmlElement(name="ID_VALUE")
private int ID_VALUE;
#XmlElement(name="EXP_DATE")
private String EXP_DATE;
public IdDetails(){}
public int getSLNO() {
return SLNO;
}
public void setSLNO(int SLNO) {
this.SLNO = SLNO;
}
public String getSOURCE_ID() {
return SOURCE_ID;
}
public void setSOURCE_ID(String SOURCE_ID) {
this.SOURCE_ID = SOURCE_ID;
}
public int getID_VALUE() {
return ID_VALUE;
}
public void setID_VALUE(int ID_VALUE) {
this.ID_VALUE = ID_VALUE;
}
public String getEXP_DATE() {
return EXP_DATE;
}
public void setEXP_DATE(String EXP_DATE) {
this.EXP_DATE = EXP_DATE;
}
}
Also, inside the same "test" package the jaxb.index file with:
DataPacket
ConsumerProfile
ConsumerDetails
IdDetails
Then, when testing with this Test class:
package test;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class Test {
public static void main(String[] args) {
try{
JAXBContext jc = JAXBContext.newInstance(DataPacket.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("input2.xml");
DataPacket dp = (DataPacket) unmarshaller.unmarshal(xml);
Body body = dp.getBODY();
ConsumerProfile profile = body.getProfile();
ConsumerDetails consumerDetail = profile.getCONSUMER_DETAILS2();
IdDetails idDetails = profile.getID_DETAILS2();
System.out.println("ConsumerDetails name:"+consumerDetail.getNAME()+
" date of birth:"+consumerDetail.getDATE_OF_BIRTH()+
" gender:"+consumerDetail.getGENDER()+
"IdDetails SLNO:"+idDetails.getSLNO()+
" SOURCE_ID:"+idDetails.getSOURCE_ID()+
" ID_VALUE:"+idDetails.getID_VALUE()+
" EXP_DATE:"+idDetails.getEXP_DATE());
}
catch(JAXBException e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}

Not able to unmarshall child object using jaxb [duplicate]

I've a very big XML string. Im posting here only part of the XML object. I'm trying to convert this XML to Java object. My first question is, should I need to create Java object of total XML tag values or can I have create the Java object of only selected inner XML objects? Please find my XML string.
<DATAPACKET REQUEST-ID = "2">
<HEADER>
<RESPONSE-TYPE CODE="1" DESCRIPTION="Response DataPacket"/>
<SEARCH-RESULT-LIST>
<SEARCH-RESULT-ITEM>
<NAME MATCHED="TRUE"/>
</SEARCH-RESULT-ITEM>
</SEARCH-RESULT-LIST>
</HEADER>
<BODY>
<CONS_SCORE>
<SCORE>0</SCORE>
<REASON1>
<HEADER></HEADER>
<DESCRIPTION></DESCRIPTION>
</REASON1>
<REASON2>
<HEADER></HEADER>
<DESCRIPTION></DESCRIPTION>
</REASON2>
<REASON3>
<HEADER></HEADER>
<DESCRIPTION></DESCRIPTION>
</REASON3>
<REASON4>
<HEADER></HEADER>
<DESCRIPTION></DESCRIPTION>
</REASON4>
</CONS_SCORE>
<CONSUMER_PROFILE2>
<CONSUMER_DETAILS2>
<RUID>1234</RUID>
<NAME>ABC</NAME>
<DATE_OF_BIRTH>1980-03-03T00:00:00+03:00</DATE_OF_BIRTH>
<GENDER>001</GENDER>
</CONSUMER_DETAILS2>
<ID_DETAILS2>
<SLNO>1</SLNO>
<SOURCE_ID>001</SOURCE_ID>
<ID_VALUE>2806</ID_VALUE>
<EXP_DATE>2018-07-13T00:00:00+03:00</EXP_DATE>
</ID_DETAILS2>
</CONSUMER_PROFILE2>
</BODY>
</DATAPACKET>
In the above object, I want to fetch only CONSUMER_PROFILE2 object. Here is my Dto class
#XmlRootElement(name = "DATAPACKET")
public class ConsumerProfileDto {
private ConsumerDetailsDto CONSUMER_DETAILS2;
private IdDetailsDto ID_DETAILS2;
public ConsumerDetailsDto getCONSUMER_DETAILS2() {
return CONSUMER_DETAILS2;
}
public void setCONSUMER_DETAILS2(ConsumerDetailsDto cONSUMER_DETAILS2) {
CONSUMER_DETAILS2 = cONSUMER_DETAILS2;
}
public IdDetailsDto getID_DETAILS2() {
return ID_DETAILS2;
}
public void setID_DETAILS2(IdDetailsDto iD_DETAILS2) {
ID_DETAILS2 = iD_DETAILS2;
}
}
CONSUMER_DETAILS2 class
#XmlRootElement(name = "CONSUMER_DETAILS2")
public class ConsumerDetailsDto {
private String NAME;
private String DATE_OF_BIRTH;
private String GENDER;
private String NATIONALITY;
public String getNAME() {
return NAME;
}
public void setNAME(String nAME) {
NAME = nAME;
}
public String getDATE_OF_BIRTH() {
return DATE_OF_BIRTH;
}
public void setDATE_OF_BIRTH(String dATE_OF_BIRTH) {
DATE_OF_BIRTH = dATE_OF_BIRTH;
}
public String getGENDER() {
return GENDER;
}
public void setGENDER(String gENDER) {
GENDER = gENDER;
}
public String getNATIONALITY() {
return NATIONALITY;
}
public void setNATIONALITY(String nATIONALITY) {
NATIONALITY = nATIONALITY;
}
Here is the code of unmarshalling
JAXBContext jaxbContext = JAXBContext.newInstance(ConsumerProfileDto.class);
StringReader reader = new StringReader(responseXML);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
ConsumerDetailsDto que= (ConsumerDetailsDto) jaxbUnmarshaller.unmarshal(reader);
System.out.println(que.getDATE_OF_BIRTH());
System.out.println(que.getGENDER());;
System.out.println(que.getNAME());
P.S
I've used DocumentBuilder and I'm able to fetch the values using it. But, I want to extract using Jaxb.
You can't annotate as #XmlRootElement the Java class mirroring the XML element that you're interested on. You have to mirror in Java all the XML elements from the topmost element in the XML file (DATAPACKET) to the lowest ones (CONSUMER_DETAILS2 and ID_DETAILS2) in the path that you're interested, even if you're only interested in some of them.
I assume that the operator isn't interested in RUID (because the class CONSUMER_DETAILS2 doesn't include a field for this XML element), and also that the field NATIONALITY is not going to be loaded from this XML.
If the input XML of the question were in a file named input2.xml, then I'd have the following Java classes:
DataPacket
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.NONE)
#XmlRootElement(name = "DATAPACKET")
public class DataPacket {
#XmlAttribute(name = "REQUEST_ID")
private int REQUEST_ID;
#XmlElement(name ="BODY")
private Body BODY;
public DataPacket(){}
public int getREQUEST_ID() {
return REQUEST_ID;
}
public void setREQUEST_ID(int REQUEST_ID) {
this.REQUEST_ID = REQUEST_ID;
}
public Body getBODY() {
return BODY;
}
public void setBODY(Body BODY) {
this.BODY = BODY;
}
}
Body
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.NONE)
class Body {
#XmlElement(name = "CONSUMER_PROFILE2")
private ConsumerProfile profile;
public Body(){}
public ConsumerProfile getProfile() {
return profile;
}
public void setProfile(ConsumerProfile profile) {
this.profile = profile;
}
}
ConsumerProfile
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.NONE)
public class ConsumerProfile {
#XmlElement(name = "CONSUMER_DETAILS2")
private ConsumerDetails CONSUMER_DETAILS2;
#XmlElement(name = "ID_DETAILS2")
private IdDetails ID_DETAILS2;
public ConsumerProfile(){}
public ConsumerDetails getCONSUMER_DETAILS2() {
return CONSUMER_DETAILS2;
}
public void setCONSUMER_DETAILS2(ConsumerDetails cONSUMER_DETAILS2) {
CONSUMER_DETAILS2 = cONSUMER_DETAILS2;
}
public IdDetails getID_DETAILS2() {
return ID_DETAILS2;
}
public void setID_DETAILS2(IdDetails iD_DETAILS2) {
ID_DETAILS2 = iD_DETAILS2;
}
}
ConsumerDetails
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.NONE)
class ConsumerDetails {
#XmlElement(name="NAME")
private String NAME;
#XmlElement(name="DATE_OF_BIRTH")
private String DATE_OF_BIRTH;
#XmlElement(name="GENDER")
private String GENDER;
private String NATIONALITY;
public ConsumerDetails(){}
public String getNAME() {
return NAME;
}
public void setNAME(String nAME) {
NAME = nAME;
}
public String getDATE_OF_BIRTH() {
return DATE_OF_BIRTH;
}
public void setDATE_OF_BIRTH(String dATE_OF_BIRTH) {
DATE_OF_BIRTH = dATE_OF_BIRTH;
}
public String getGENDER() {
return GENDER;
}
public void setGENDER(String gENDER) {
GENDER = gENDER;
}
public String getNATIONALITY() {
return NATIONALITY;
}
public void setNATIONALITY(String nATIONALITY) {
NATIONALITY = nATIONALITY;
}
}
IdDetails
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.NONE)
class IdDetails {
#XmlElement(name="SLNO")
private int SLNO;
#XmlElement(name="SOURCE_ID")
private String SOURCE_ID;
#XmlElement(name="ID_VALUE")
private int ID_VALUE;
#XmlElement(name="EXP_DATE")
private String EXP_DATE;
public IdDetails(){}
public int getSLNO() {
return SLNO;
}
public void setSLNO(int SLNO) {
this.SLNO = SLNO;
}
public String getSOURCE_ID() {
return SOURCE_ID;
}
public void setSOURCE_ID(String SOURCE_ID) {
this.SOURCE_ID = SOURCE_ID;
}
public int getID_VALUE() {
return ID_VALUE;
}
public void setID_VALUE(int ID_VALUE) {
this.ID_VALUE = ID_VALUE;
}
public String getEXP_DATE() {
return EXP_DATE;
}
public void setEXP_DATE(String EXP_DATE) {
this.EXP_DATE = EXP_DATE;
}
}
Also, inside the same "test" package the jaxb.index file with:
DataPacket
ConsumerProfile
ConsumerDetails
IdDetails
Then, when testing with this Test class:
package test;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class Test {
public static void main(String[] args) {
try{
JAXBContext jc = JAXBContext.newInstance(DataPacket.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("input2.xml");
DataPacket dp = (DataPacket) unmarshaller.unmarshal(xml);
Body body = dp.getBODY();
ConsumerProfile profile = body.getProfile();
ConsumerDetails consumerDetail = profile.getCONSUMER_DETAILS2();
IdDetails idDetails = profile.getID_DETAILS2();
System.out.println("ConsumerDetails name:"+consumerDetail.getNAME()+
" date of birth:"+consumerDetail.getDATE_OF_BIRTH()+
" gender:"+consumerDetail.getGENDER()+
"IdDetails SLNO:"+idDetails.getSLNO()+
" SOURCE_ID:"+idDetails.getSOURCE_ID()+
" ID_VALUE:"+idDetails.getID_VALUE()+
" EXP_DATE:"+idDetails.getEXP_DATE());
}
catch(JAXBException e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}

Unmarshalling following xml having inheritance structure with JAXB

I want to unmarshal this xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response>
<command>dir</command>
<directory name="folder">
<file>
<lastModified>2016-06-06 12:45 AM</lastModified>
<name>input.txt</name>
<size>123</size>
<type>file</type>
</file>
<file>
<lastModified>2016-06-06 12:45 AM</lastModified>
<name>data.txt</name>
<size></size>
<type>directory</type>
</file>
</directory>
</response>
here is my class structure
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
#XmlRootElement
#XmlSeeAlso({MessageResponse.class})
class Response {
String command;
public Response() {
}
#XmlElement
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
}
#XmlRootElement
class MessageResponse extends Response{
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class DirListingResponse extends Response{
String name;
Directory directory;
#XmlElement
public Directory getDirectory() {
return directory;
}
public void setDirectory(Directory directory) {
this.directory = directory;
}
}
class Directory {
ArrayList<File> file;
String name;
public Directory() {
}
#XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement
public ArrayList<File> getFile() {
return file;
}
public void setFile(ArrayList<File> file) {
this.file = file;
}
}
class File {
String name, type;
String lastModified;
long size;
public File() {
}
public File(String name, String type, String lastModified, long size) {
this.name = name;
this.type = type;
this.lastModified = lastModified;
this.size = size;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
}
and the main class
try {
jaxbContext = JAXBContext.newInstance(Response.class);
jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Object obj = jaxbUnmarshaller.unmarshal(new InputSource(new StringReader(inputXml)));
} catch (JAXBException e) {
e.printStackTrace();
}
but this is not working accordingly. obj contains only command field of response class due to not the proper annotation. Under "response" tag "directory" and "message" tag appears based on command fired. If the command is "dir" then "directory" tag otherwise "message" tag. So I want this unmarshal and save the result in relative inherited class. How can I solve this ?
One solution although not elegant is to
read the input XML beforehand and check if it has <directory or <message
accordingly instantiate the jaxbcontext.
jaxbContext = JAXBContext.newInstance(MessageResponse.class);
or
jaxbContext = JAXBContext.newInstance(DirListingResponse.class);
I have a solution which uses the Sax-Parser. I uploaded it to Github. There should be better solutions (including implicit typings). But this would solve your problems, while creating new ones. Changes to File and Directory, etc. would introduce changes in the corresponding handlers...

JAXB map to object insteadof string

I have the following XML:
<game name="m1itskow" sourcefile="maygay1bsw.c" ismechanical="yes" cloneof="m1itsko" romof="m1itsko">
<description>It's A Knockout (Maygay) (M1A/B) (set 24)</description>
<year>199?</year>
<manufacturer>Maygay</manufacturer>
</game>
Today I have manufacturer as a String inside Game class, but I need to map to a Manufacturer class, how should I do it? Is it possible? thanks.
edit: The XML cannot be changed because this is a generated file by a 3rd party tool.
Made changes in xml structure
XML
<?xml version="1.0" encoding="UTF-8"?>
<game name="m1itskow" sourcefile="maygay1bsw.c" ismechanical="yes" cloneof="m1itsko" romof="m1itsko">
<description>It's A Knockout (Maygay) (M1A/B) (set 24)</description>
<year>199?</year>
<manufacturer>
<manufacturer-name>Maygay</manufacturer-name>
</manufacturer>
</game>
POJO game and manufacturer...
game.java
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class game {
private String name;
private String sourcefile;
private String ismechanical;
private String cloneof;
private String romof;
private String description;
private String year;
private Manufacturer manufacturer=new Manufacturer();
public game() {}
#XmlAttribute
public String getIsmechanical() {
return ismechanical;
}
public void setIsmechanical(String ismechanical) {
this.ismechanical = ismechanical;
}
#XmlAttribute
public String getCloneof() {
return cloneof;
}
public void setCloneof(String cloneof) {
this.cloneof = cloneof;
}
#XmlAttribute
public String getRomof() {
return romof;
}
public void setRomof(String romof) {
this.romof = romof;
}
#XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlAttribute
public String getSourcefile() {
return sourcefile;
}
public void setSourcefile(String sourcefile) {
this.sourcefile = sourcefile;
}
#XmlElement
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#XmlElement
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
#XmlElement(name="manufacturer")
public Manufacturer getManufacturer() {
return manufacturer;
}
public void setManufacturer(Manufacturer manufacturer) {
this.manufacturer=manufacturer;
}
}
manufacturer.java
i
mport java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="manufacturer")
public class Manufacturer implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String Name;
#XmlElement(name="manufacturer-name")
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
main.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class SampleTest {
public static void main(String[] args) {
try {
File file = new File("employee.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(game.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
game e=(game) jaxbUnmarshaller.unmarshal(file);
System.out.println(e.getManufacturer().getName());
}
catch (JAXBException e) {
e.printStackTrace();
}
}
}

Categories