I have a Java class which contains a List field.
public class Machine{
public int ID;
public String Name;
public String Status;
public String Environment;
public String Cluster;
public List<String> SupportedLocales;
}
Below is an instance of the class in XML that I am trying to unmarshall.
<?xml version="1.0" encoding="utf-8"?>
<Machine xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>27</ID>
<Name>QA14ADMINOPM201</Name>
<Status>Decom</Status>
<Environment>QA14</Environment>
<Cluster>ADMINOPM</Cluster>
<SupportedLocales>
<SupportedLocale>NA</SupportedLocale>
<SupportedLocale>Global</SupportedLocale>
</SupportedLocales>
</Machine>
When I unmarshall the Xml though, the resulting object has an empty SupportedLocales list, with no elements. Any reason why this might be happening or suggested fixes? All other fields are being unmarshalled correctly.
Annotate your field with an XmlElementWrapper annotation:
#XmlElementWrapper(name = "SupportedLocales")
#XmlElement(name = "SupportedLocale")
public List<String> SupportedLocales;
Also try to follow the convention of using variables that start with a lowercase (supportedLocales instead of SupportedLocales). This would need to map the XML element name for each field as follows:
#XmlElement(name="ID")
public int id;
#XmlElement(name="Name")
public String name;
#XmlElement(name="Status")
public String status;
#XmlElement(name="Environment")
public String environment;
#XmlElement(name="Cluster")
public String cluster;
#XmlElementWrapper(name = "SupportedLocales")
#XmlElement(name = "SupportedLocale")
public List<String> supportedLocales;
Related
If i declare the namespace on the root element, like this:
#JacksonXmlRootElement(namespace = "urn:stackify:jacksonxml", localName = "PersonData")
public class Person {
private String id;
private String name;
private String note;
}
It produces:
<PersonData xmlns="urn:stackify:jacksonxml">
<id xmlns="">12345</id>
<name xmlns="">Graham</name>
<note xmlns="">Hello</note>
</PersonData>
But I want the namespace only on the root element. The xmlns attribute should not appear on child elements.
How can i archive this?
There is a workaround which I found more elegant for me.
You may define constant for your namespace like this:
#JacksonXmlRootElement(localName = "PersonData")
public class Person {
#JacksonXmlProperty(isAttribute = true)
private final String xmlns = "urn:stackify:jacksonxml";
private String id;
private String name;
private String note;
}
You need to specify the same namespace as the root element in each attribute:
#JacksonXmlRootElement(namespace = "urn:stackify:jacksonxml", localName = "PersonData")
public class Person {
#JacksonXmlProperty(namespace = "urn:stackify:jacksonxml")
private String id;
#JacksonXmlProperty(namespace = "urn:stackify:jacksonxml")
private String name;
#JacksonXmlProperty(namespace = "urn:stackify:jacksonxml")
private String note;
}
Its a bit tiresome, but its the only way I found to avoid the unnecessary namespaces.
Also works well with immutables library and json annotations (if you need to serialize/deserialize both in JSON and in XML)
#Value.Immutable
#JsonRootName(value = "PersonData", namespace = "urn:stackify:jacksonxml")
public interface Person extends Serializable {
}
Is it possible to rename the parameters used inside a GET webservice in spring? Like search.limitResults in the following example:
localhost:8080/firstname=test&search.limitResults=10
You get the idea. Can this be achieved?
#RestController
public class MyServlet {
#RequestMapping(value = "/", method = RequestMethod.GET)
private String test(RestParams p) {
}
}
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class RestParams {
private String firstname;
private String lastname;
//is that possible to nest?
#XmlElement(name = "search")
private MyComplexSearch search;
public MyComplexSearch getSearch() {return search;}
public void setSearch(MyComplexSearch) {this.search = search;}
#XmlRootElement(name = "search")
#XmlAccessorType(XmlAccessType.FIELD)
public class MyComplexSearch {
private int limitResults;
//some more
}
}
The request will not work with the code above. Instead one would have to use myComplexSearch as the objects name.
localhost:8080/firstname=test&myComplexSearch.limitResults=10
How can I redefine the name of the input property, without having to rename the java class itself?
Nested classes have to be static.
public static class MyComplexSearch
i have problem with my jaxb EclipseLink implementation.
Let's assume I have the following Entity ...
#XmlRootElement(name = GenericConfigEntity.XML_ROOT_TAG)
public class GenericConfigEntity {
private String name;
private String data;
private String version;
private String date;
private String template;
#XmlAttribute(name = GenericConfigEntity.XML_NAME)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement(name = GenericConfigEntity.XML_DATA)
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
#XmlAttribute(name = GenericConfigEntity.XML_VERSION)
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
#XmlAttribute(name = GenericConfigEntity.XML_DATE)
public String getDate() {
return date;
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
}
The string 'template' contains xml data already let's say someting like this (in my real context it is a lot more and I do not want to create the entities for this).
<Prozess name="xx" test="1">
<Debug system="test" />
</Prozess>
Now my question is if there is a way to integrate the template string into the marshalling process that someting like this is generated
<conf name="xx" version="x" datum="xx">
<Prozess name="xx" test="1">
<Debug system="test" />
</Prozess>
<Data>
TextTextText
</Data>
</conf>
It is no solution to wrap the template in an tag because i am restricted to this layout.
Also #XmlValue is no solution because I get an exception "all other elements have to be an attribute because one is marked as xmlvalue".
I haven't used this myself yet, but I reckon you could use the #XmlAnyElement in conjunction with a DomHandler to implement such a mapping. You can find a helpful example in the blog of MOXy's lead programmer here.
I think you'd still have to make sure that the XML content in your template field has at least an opening and a closing tag, which serve to identify the DOM element during (un)marshalling. That tag may be arbitrary as required by you. I guess you could just look for the first tag appearing in the string and try to match it against the end of the string.
I know to create a JAXB Class to marshal/unmarshall an xml like this
<outertag>
<innerelement>
<innerElementDetail1>some value</inner-element-detail1>
</innerelement>
</outertag>
here is the class I created
#XmlRootElement(name ="outertag")
#XmlAccessorType(XmlAccessType.FIELD)
public class OuterTag {
#XmlElement(name = "innerelement")
private List<InnerElement> innerElemements
public static InnerElement{
private String innerElementDetail;
// getters and setters
}
}
If I have to have an attribute on one of the inner elements like this
<outertag>
<innerelement attribute1="attribute1value">
<innerElementDetail1>some value</inner-element-detail1>
</innerelement>
</outertag>
how do I do that ?
This should do it :
#XmlRootElement(name ="outertag")
#XmlAccessorType(XmlAccessType.FIELD)
public class OuterTag {
#XmlElement(name = "innerelement")
private List<InnerElement> innerElemements
public static InnerElement{
#XmlAttribute(name = "attribute1")
protected String attribute1;
private String innerElementDetail;
// getters and setters
}
}
I have an xml. I want to convert to object , xstream convert well all tags except one of them it gives null.
Any idea about this problem ?
xml:
<person>
<name>nnn</name>
<age>aaa</age>
<address>
<city>ccc</city>
<countryco</country>
</address>
</person>
Code java
XStream _xstream = new XStream();
_xstream.setMode(XStream.NO_REFERENCES);
_xstream.aliasType("person", PersonType.class);
_xstream.aliasType("address", PersonType.class);
_xstream.aliasField("city", AddressType.class, "city");
_xstream.aliasField("country", AddressType.class, "country");
When I inspect the object person , all variables are ok , but address is always null
i tried this :
_xstream.aliasType("person", PersonType.class);
_xstream.aliasType("address", AddressType.class);
_xstream.aliasField("city", AddressType.class, "city");
_xstream.aliasField("country", AddressType.class, "country");
but still don't work !
In this case the usage of alias are redundant. XStream will convert the names of the fields automaticly.
How ever you adress seems to be an nested type. You are using the same type for two aliases:
_xstream.aliasType("person", PersonType.class);
_xstream.aliasType("address", PersonType.class);
it should be
_xstream.aliasType("address", AddressType.class);
for adress alias.
Java Code:
#XStreamAlias("person")
public class Person {
#XStreamAlias("name")
private String Name;
#XStreamAlias("age")
private long Age;
#XStreamImplicit(itemFieldName = "address")
private List addresses = new ArrayList();
}
#XStreamAlias("adress")
public class Address{
#XStreamAlias("city")
private String City;
#XStreamAlias("country")
private String Country;
}
Main Code:
FileReader reader = new FileReader("file.xml"); // load file
XStream xstream = new XStream();
xstream.processAnnotations(Person.class);
xstream.processAnnotations(Address.class);
Person person = (Person) xstream.fromXML(reader);
I believe address would be a reference of object Address in your class Person. If so then you need to do like this:
Person.java
public class Person{
private String name;
private int age;
private Address address;
public String getName(){
return name;
}
public int getAge(){
return age;}
public String getcity(){
return address.getCity();
}
public String getCountry(){
return address.getCountry();
}
}
Address.java
public class Address {
private String city;
private String country;
public String getCity(){
return city;
}
public String getCountry(){
return country;
}
}
JAVA CODE
FileReader xmlReader = new FileReader("file.xml"); // load file
XStream stream = new XStream(new StaxDriver());
stream.alias("person",Person.class);//Since in your xml file `person` is tag
Person person = (Person) stream.fromXML(xmlReader);
System.out.println("Name:"+person.getName()+"\nAge:"+person.getAge()+
"\nCity:"+person.getCity()+"\nCountry:"+person.getCountry();