I want to give custom names to the xml root element and to list elements.
But the annotations don't work.
#XmlRootElement(name = "test")
#XmlAccessorType(XmlAccessType.FIELD)
public class TestRsp {
#XmlElementWrapper(name = "persons")
#XmlElement(name = "pax")
private List<Person> persons;
}
public class Person {
private String name;
private String age;
}
Usage:
#RestController
public class MyServlet {
#RequestMapping("/test")
public TestRsp test() {
//...
return rsp;
}
}
Result:
<TestRsp> <!-- should be named "test" -->
<persons>
<persons> <!-- should be named "pax" -->
<name />
<age />
</persons>
<persons>
//...
</persons>
</persons>
</TestRsp>
So my xml annotations are not picked up. But why?
Try using #JsonProperty annotation.
It should look something like thit:
#JsonProperty("test")
EDIT 1:
Try annotating the getter of the fields that you want to change like so:
#XmlElement(name="someName")
EDIT 2:
#XmlRootElement(name="persons")
public class Root {
private List<String> someList;
#XmlElement(name="pax")
public List<String> getSomeList() {
return someList;
}
public void setSomeList(List<String> someList) {
this.someList = someList;
}
public Root(String numValue,List<String> someListValue) {
this();
this.number = numValue;
this.someList = someListValue;
}
/**
*
*/
public Root() {
// TODO Auto-generated constructor stub
}
}
Maybe this will provide:
<persons>
<pax>FOO</pax>
<pax>BAR</pax>
</persons>
EDIT 3:
Maybe if you want to make your solution works you need to add a file called jaxb.properties in with your model classes with the following entry:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
It turned out I have to use #JacksonXml* annotations instead:
#JacksonXmlRootElement(localName = "test")
public class TestRsp {
#JacksonXmlElementWrapper(localName = "persons")
#JacksonXmlProperty(localName = "pax")
#JsonProperty(name = "persons")
private List<Person> persons;
}
Related
I need to marshall a java class to get a xml, but i don't know how to delete a tag inside the one generated.
I have a class with an object list with this form
#XmlRootElement(name = "Element")
public class Element {
private List<Foo> foos;
#XmlElementWrapper("fooList")
public List<Foo> getfoos() {
return foos;
}
public void setFoos(List<Foo> foos) {
this.foos = foos;
}
}
And the class Foo of the list is lie this:
#XmlRootElement
public class Foo {
private String id;
private String code;
#XmlElement
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
When marshalling to get xml I get this:
<Element>
<fooList>
<foos>
<string1>asd</string1>
<string2>qwe</string2>
</foos>
<foos>
<string1>poi</string1>
<string2>lkj</string2>
</foos>
</fooList>
</Element>
But I want to get it without the tag foos, like this:
<Element>
<fooList>
<string1>asd</string1>
<string2>qwe</string2>
<string1>poi</string1>
<string2>lkj</string2>
</fooList>
</Element>
Can anyone help me?
Thanks a lot!!
You could do something like this:
#XmlRootElement(name = "Element")
#XmlAccessorType(XmlAccessType.FIELD)
public class Element {
#XmlElementWrapper(name = "fooList")
#XmlElements({
#XmlElement(name = "id", type = Id.class),
#XmlElement(name = "code", type = Code.class),
})
private List<FooItem> foos;
public List<FooItem> getfoos() {
return foos;
}
public void setFoos(List<FooItem> foos) {
this.foos = foos;
}
}
and then Id and Code classes look similar:
public class Id implements FooItem {
#XmlValue
private String id;
public Id() {}
public Id(String id) {
this.id = id;
}
}
They are bounded by an interface that doesn't do much:
public interface FooItem { }
This structure will allow you to marshal into xml as the one you specified you need.
The challenge with the class structure you had is that class Foo had 2 fields and #XmlValue can be applied only to one field per class. So having 2 fields "forces" them to stand for #XmlElement and they in turn have to be children of an xml element. This is why you had the "intermediate" foo elements in your xml for each Foo instance in your List.
I'm struggling saving all data from my class/subclass using JAXB.
I want to save all accounts from an observableList, but the problem is, the account class
public class Account{
private ObjectProperty<HosterObject> host;
....
}
contains an HosterObject which has 2 attributes:
publicName and privateName also have getter and setter.
#XmlRootElement(name = "hoster")
public class HosterObject {
private final StringProperty publicName;
private final StringProperty privateName;
public HosterObject(String publicName, String privateName){
this.publicName = new SimpleStringProperty(publicName);
this.privateName = new SimpleStringProperty(privateName);
}
#XmlElement(name = "publicName")
public StringProperty publicNameProperty(){
return publicName;
}
#XmlElement(name = "privateName")
public StringProperty privateNameProperty(){
return privateName;
}
How can I save the content from the Hosterobject as Element in the xml-file as well?
At the moment the xml file looks so:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<accounts>
<account>
<hoster/>
<password>123</password>
<status>unchecked</status>
<username>test</username>
</account>
</accounts>
But i should look kinda like this
...
<account>
<hoster>
<publicName>Name</publicName>
<privateName>private Name</privateName>
</hoster>
....
</account>
....
The code for saving:
public void saveAccountDataToFile(File file) {
try {
JAXBContext context = JAXBContext.newInstance(AccountListWrapper.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Wrapping our person data.
AccountListWrapper wrapper = new AccountListWrapper();
wrapper.setAccounts(accountData);
// Marshalling and saving XML to the file.
m.marshal(wrapper, file);
} catch (Exception e) {
}
}
Wrapper:
#XmlRootElement(name = "accounts")
public class AccountListWrapper {
private List<Account> accounts;
#XmlElement(name = "account")
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
}
Thanks in advance!
Add:
tag HosterObject by
#XmlRootElement(name = "hoster")
#XmlElement
for class and set method for HosterObject in Account.
public HosterObject (){}
public Account(){}
JAXB need default empty constructor.
If you want to add class to xml you must tag it and create always default public constructor. Remember to tag only class which are non abstract.
I am trying unmarshal XML to object with wrapped elements.
XML looks:
<?xml version="1.0" encding="utf-8"?>
<Output xmlns="_xxx_" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Companies>
<Company>
...
</Company>
<Company>
...
</Company>
...
</Companies>
<People>
<Person>
...
</Person>
<Person>
...
</Person>
...
</People>
<Relations>
<Relation>
...
</Relation>
<Relation>
...
</Relation>
...
</Relations>
<Info ... />
</Output>
I would like to have Compenies, People and Relations in Lists. I try this code, but it doesn't work:
Java Code
Ouput
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Output", namespace = "_xxx_")
#XmlType(propOrder={"companies", "people", "relations", "info"})
public class Output {
#XmlElementWrapper(name = "Companies")
#XmlElement(name = "Company" type = Company.class)
private List<Company> companies;
#XmlElementWrapper(name = "People")
#XmlElement(name = "Person", type = Person.class)
private List<Person> people;
#XmlElementWrapper(name = "Relations")
#XmlElement(name = "Relation", type = Relation.class)
private List<Relation> relations;
#XmlElement(name = "Info")
private Info info;
public Output() {
this.companies = new ArrayList<>();
this.people = new ArrayList<>();
this.relations = new ArrayList<>();
}
public List<Company> getCompanies() {
return companies;
}
public void setCompanies(List<Company> companies) {
this.companies = companies;
}
public List<Person> getPeople() {
return people;
}
public void setPeople(List<Person> people) {
this.people = people;
}
public List<Relation> getRelations() {
return relations;
}
public void setRelations(List<Relation> relations) {
this.relations = relations;
}
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
}
And for example Company looks (other classes are similar)
#XmlRootElement(name = "Company")
public class Company {
...
}
If I use this it creates empty Lists, but, if I change code to:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Output", namespace = "_xxx_")
#XmlType(propOrder={"companies", "people", "relations", "info"})
public class Output {
#XmlElement(name = "Companies")
private Companies companies;
#XmlElement(name = "People")
private People people;
....
public Companies getCompanies() {
return companies;
}
public void setCompanies(Companies companies) {
this.companies = companies;
}
...
}
where Companies class looks:
#XmlRootElement(name = "Companies")
#XmlAccessorType (XmlAccessType.FIELD)
public class Companies {
#XmlElement(name = "Company")
private List<Company> companies;
public List<Company> getCompanies() {
return companies;
}
public void setCompanies(List<Company> companies) {
this.companies = companies;
}
}
it works fine, but it isn't nice solution.
Can anyone advise me what is wrong here? Thanks :)
I solved my problem by using the instructions on this link. I use mapping to java.util.Map.
I have the following XML file to unmarshall
<root>
<emp>Google</emp>
<emp>Yahoo</emp>
<xyz>random</xyz>
</root>
And i have used annotations in the following way,
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp")
private String emp1;
#XmlElement(name = "emp")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
My problem is while i'm trying to get
obj.getEmp1(); // result is Yahoo instead of Google
obj.getEmp2(); // result is null.
Kindly clarify me, what am i doing wrong?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
The standard JAXB (JSR-222) annotations do not support mapping 2 different properties to the same XML element.
You could use EclipseLink JAXB (MOXy)'s #XmlPath extension for this use case.
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlPath("emp[1]/text()")
private String emp1;
#XmlPath("emp[2]/text()")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
If for whatever reason you cannot use MOXy, another solution would be to map the emp element as a list
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp")
private List<String> emp;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
And then use the following code to get the values:
obj.getEmp().get(0);
obj.getEmp().get(1);
But Blaise's solution is more elegant
You could have a String[] field and have your current accessor methods access the String[].
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
private String[] emp = new String[2];
private String xyz;
public String getEmp1() {
return emp[0];
}
public void setEmp1(String emp1) {
this.emp[0] = emp1;
}
public String getEmp2() {
return emp[1];
}
public void setEmp2(String emp2) {
this.emp[1] = emp2;
}
public String getXyz() {
return xyz;
}
public void setXyz(String xyz) {
this.xyz = xyz;
}
}
This might work.
<root>
<emp1>Google</emp1>
<emp2>Yahoo</emp2>
<xyz>random</xyz>
</root>
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp1")
private String emp1;
#XmlElement(name = "emp2")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
}
I was going through the Blaise's Blog http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html for Jaxb Inheritance using Substitution.
I want to implement the same but not to the root element. I am looking this type of XML as a output.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<customer>
<address>
<street>1 A Street</street>
</address>
<address>
<street>2 B Street</street>
</address>
<phoneNumber>
<mobileNo>xxx-xxx-xxxx</mobileNo>
</phoneNumber>
</customer>
</configuration>
Following is the Configuration.java
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Configuration {
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
#Override
public String toString() {
return "\n Customer[ customer="+customer+"]";
}
}
Customer.java
public class Customer {
private List<ContactInfo> contactInfo;
#XmlElementRef
public List<ContactInfo> getContactInfo() {
return contactInfo;
}
public void setContactInfo(List<ContactInfo> contactInfo) {
this.contactInfo = contactInfo;
}
}
Address.java
public class Address extends ContactInfo {
private String street;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
PhoneNumber.java
public class PhoneNumber extends ContactInfo{
private String mobileNo;
public String getMobileNo() {
return mobileNo;
}
public void setMobileNo(String mobileNo) {
this.mobileNo = mobileNo;
}
}
Demo.java
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
Configuration configuration = new Configuration();
Customer customer = new Customer();
List<ContactInfo> contacts = new ArrayList<ContactInfo>();
Address address = new Address();
address.setStreet("1 A Street");
contacts.add(address);
Address address1 = new Address();
address1.setStreet("2 B Street");
contacts.add(address1);
PhoneNumber phone = new PhoneNumber();
phone.setMobileNo("408 431 8829");
contacts.add(phone);
customer.setContactInfo(contacts);
configuration.setCustomer(customer);
JAXBContext jc = JAXBContext.newInstance(Configuration.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(configuration, System.out);
}
}
Presently I am getting following Exception
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Invalid #XmlElementRef : Type "class Address" or any of its subclasses are not known to this context.
Could anybody help me out on this?
Thanks,
Kwatra
Issue #1 - The Subclasses
A JAXB (JSR-222) implementation can not auto discover subclasses. You can solve the first exception by using an #XmlSeeAlso annotation on the ContactInfo class to reference the subclasses:
#XmlSeeAlso({Address.class, PhoneNumber.class})
public class ContactInfo {
}
Or you can reference them when you create the JAXBContext.
JAXBContext jc = JAXBContext.newInstance(Configuration.class, Address.class, PhoneNumber.class);
Issue #2 - The Mapping
When using #XmlElementRef you need to pair it with #XmlRootElement. If you don't want to go this route you could use #XmlElements instead.
#XmlElements({
#XmlElement(name="address", type=Address.class),
#XmlElement(name="phoneNumber", type=PhoneNumber.class)
})
public List<ContactInfo> getContactInfo() {
return contactInfo;
}
http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html