I am trying to unmarshal xml file to java object. Here's the xml file. I am not sure if we can unmarshal file like below xml. Because it has multiple account types and has the same tags couple of times. Will this be a problem for unmarshalling?
<?xml version="1.0" encoding="UTF-8"?>
<AccountTypes>
<AccountType>
<AccountTypeId>1</AccountTypeId>
<AccountTypeDescription>savings</AccountTypeDescription>
</AccountType>
<AccountType>
<AccountTypeId>2</AccountTypeId>
<AccountTypeDescription>checking</AccountTypeDescription>
</AccountType>
<AccountType>
<AccountTypeId>3</AccountTypeId>
<AccountTypeDescription>401k</AccountTypeDescription>
</AccountType>
</AccountTypes>
My Code is like this: XmlToJava.java
public static void main(Strings[] args){
try {
File file = new File("pathname");
JAXBContext context = JAXBContext.newInstance(Account.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Account account = (Account) unmarshaller.unmarshal(file);
} catch(Exception e){
e.printStackTrace();
}
}
My POJO looks like this: do I have correct annotations?
@XmlRootElement(name="AccountTypes")
@XmlAccessorType(XmlAccessType.FIELD)
public class Account implements Serializable{
@XmlElement(required= true)
private Integer accountTypeId;
@XmlElement(required=true)
private String description;
//has all getters, setters, contructors, toString() menthod
}
CodePudding user response:
I can see that you have a number of accounts inside the XML file, so you actually should be unmarshalling a Collection<Account>
.
Or alternatively you can have a wrapper class I believe:
@XmlRootElement(name="AccountTypes")
@XmlAccessorType(XmlAccessType.FIELD)
public final class AccountTypes implements Serializable {
@XmlElement(name="AccountType")
private List<Account> accounts = /* whatever structure you prefer */;
}
I also would rather have the POJO like this:
@XmlRootElement(name="AccountType")
@XmlAccessorType(XmlAccessType.FIELD)
public class Account implements Serializable {
@XmlElement(required=true, name="AccountTypeId")
private Integer id;
@XmlElement(required=true, name="AccountTypeDescription")
private String description;
}
It just makes sense to use account.getId()
instead of large account.getAccountTypeId()
.
Note that the Account
is name=AccountType
and AccountTypes
is name=AccountTypes
and I also fixed the name="AccountTypeDescription"
.
CodePudding user response:
Try this way:
The POJO:
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "accountType" })
@XmlRootElement(name = "AccountTypes")
public class AccountTypes {
@XmlElement(name = "AccountType", required = true)
protected List<AccountTypes.AccountType> accountType;
public List<AccountTypes.AccountType> getAccountType() {
if (accountType == null) {
accountType = new ArrayList<>();
}
return this.accountType;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "accountTypeId", "accountTypeDescription" })
public static class AccountType {
@XmlElement(name = "AccountTypeId")
@XmlSchemaType(name = "unsignedByte")
protected short accountTypeId;
@XmlElement(name = "AccountTypeDescription", required = true)
protected String accountTypeDescription;
public short getAccountTypeId() {
return accountTypeId;
}
public void setAccountTypeId(short value) {
this.accountTypeId = value;
}
public String getAccountTypeDescription() {
return accountTypeDescription;
}
public void setAccountTypeDescription(String value) {
this.accountTypeDescription = value;
}
}
}
Test:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Demo1 {
public static void main(String[] args) throws JsonProcessingException, FileNotFoundException {
ObjectMapper mapper = new ObjectMapper();
FileInputStream file = new FileInputStream ("pathname");
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
"<AccountTypes>\r\n"
" <AccountType>\r\n"
" <AccountTypeId>1</AccountTypeId>\r\n"
" <AccountTypeDescription>savings</AccountTypeDescription>\r\n"
" </AccountType>\r\n"
"<AccountType>\r\n"
" <AccountTypeId>2</AccountTypeId>\r\n"
" <AccountTypeDescription>checking</AccountTypeDescription>\r\n"
" </AccountType>\r\n"
"<AccountType>\r\n"
" <AccountTypeId>3</AccountTypeId>\r\n"
" <AccountTypeDescription>401k</AccountTypeDescription>\r\n"
" </AccountType>\r\n"
"</AccountTypes>";
AccountTypes AccountTypes = convertXMLToObject(AccountTypes.class, xml);
System.out.println("mapper from string " mapper.writeValueAsString(AccountTypes));
AccountTypes AccountTypes1 = convertXMLToObject(AccountTypes.class, file);
System.out.println("mapper from file " mapper.writeValueAsString(AccountTypes1));
}
@SuppressWarnings("unchecked")
public static <T> T convertXMLToObject(Class<T> clazz, String xml) {
try {
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller um = context.createUnmarshaller();
return (T) um.unmarshal(new StringReader(xml));
} catch (JAXBException je) {
throw new RuntimeException(String.format("Exception while Unmarshaller: %s", je.getMessage()));
}
}
@SuppressWarnings("unchecked")
public static <T> T convertXMLToObject(Class<T> clazz, InputStream file) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
T obj = (T) jaxbUnmarshaller.unmarshal(file);
return obj;
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(String.format("Exception while Unmarshaller: %s", e.getMessage()));
}
}
}
Result this:
mapper from string {"accountType":[{"accountTypeId":1,"accountTypeDescription":"savings"},{"accountTypeId":2,"accountTypeDescription":"checking"},{"accountTypeId":3,"accountTypeDescription":"401k"}]}
mapper from file {"accountType":[{"accountTypeId":1,"accountTypeDescription":"savings"},{"accountTypeId":2,"accountTypeDescription":"checking"},{"accountTypeId":3,"accountTypeDescription":"401k"}]}