Selective marshalling object - java

I need to execute a selective marshalling object. For example:
There is a class Contact:
#XmlRootElement(name = "contact")
public class Contact {
private String name;
private String number;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Marshalling the object:
public static void main(String[] args) throws JAXBException {
Contact contact = new Contact();
contact.setAddress("5 Av.");
contact.setName("John");
contact.setNumber("5555555");
JAXBContext context = JAXBContext.newInstance(Contact.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(contact, System.out);
}
As a result we have:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<contact>
<address>5 street</address>
<name>John</name>
<number>5555555</number>
</contact>
Is there any simple way to perform a selective marshalling? For example, only the address to get at the output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<contact>
<address>5 street</address>
</contact>
Thanks!

When unspecified, the default is as-if the following annotation is on the class:
#XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
That means that all public member will be used by JAXB, i.e. all your getter methods.
You can either keep that default and suppress the getter methods you don't want, or you can change the default and explicitly mark the getter methods you do want processed.
To suppress a getter method, annotate with #XmlTransient:
Prevents the mapping of a JavaBean property/type to XML representation.
To change default, annotate with #XmlAccessorType(XmlAccessType.NONE):
None of the fields or properties is bound to XML unless they are specifically annotated with some of the JAXB annotations.
Then explicitly annotate desired getter methods with #XmlElement:
Maps a JavaBean property to a XML element derived from property name.
Using #XmlTransient
#XmlRootElement(name = "contact")
class Contact {
private String name;
private String number;
private String address;
#XmlTransient
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlTransient
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Using #XmlAccessorType(XmlAccessType.NONE)
#XmlRootElement(name = "contact")
#XmlAccessorType(XmlAccessType.NONE)
class Contact {
private String name;
private String number;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
#XmlElement
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Output (from both)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<contact>
<address>5 Av.</address>
</contact>

Related

JAXB - Adding same attributes to different elements

I carefully studied the discussion "JAXB Adding attributes..." and would like to move a little further.
For example, there is a following class:
#XmlRootElement(name = "company")
#XmlType(propOrder = {"id", "name", "address"})
public class Company {
private String id;
private String name;
private String address;
#XmlElement(name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "address")
public String getAddress() {
return name;
}
public void setAddress(String address) {
this.address = address;
}
}
After marshaling an object we have:
<company>
<id>1</id>
<name>Abc</name>
<address>Mountain View, United States</address>
</company>
Is there an elegant solution, - for example using annotations #XmlPaths, #XmlPath, #XmlElements, #XmlElement, - to receive as a result:
<company>
<id>1</id>
<name lang="en">Abc</name>
<address lang="en">Mountain View, United States</address>
</company>
How about creating a custom String with the lang attribute and use that instead of string
for example :
public class LangString {
#XmlValue
protected String value;
#XmlAttribute(name = "lang")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlSchemaType(name = "language")
protected String lang;
//GETTERS & SETTERS
}
Your code :
#XmlRootElement(name = "company")
#XmlType(propOrder = {"id", "name", "address"})
public class Company {
private String id;
private LangString name;
private LangString address;
#XmlElement(name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement(name = "name")
public LangString getName() {
return name;
}
public void setName(LangString name) {
this.name = name;
}
#XmlElement(name = "address")
public LangString getAddress() {
return name;
}
public void setAddress(LangString address) {
this.address = address;
}
}
The code above was generated from an xsd schema for my application that had elements with the lang attribute thus the #XmlSchemaType.
Hope it helps

How to generate JSON and XML from same entity classes?

I have the below class structure.
#XmlSeeAlso({Phone.class, Address.class})
abstract class ContactInfo {
}
#XmlRootElement(name="address")
class Address extends ContactInfo {
private String street;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
#XmlRootElement(name="phone")
class Phone extends ContactInfo {
private String mobile;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
}
class Contact {
private ContactInfo contact;
#XmlElementRef
public ContactInfo getContact() {
return contact;
}
public void setContact(ContactInfo contact) {
this.contact = contact;
}
}
#XmlRootElement(name="user")
class User {
private String name;
private Contact contact;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
}
When I convert this to XML using JAXB, I am getting the below structure.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
<contact>
<phone>
<mobile>8971829749</mobile>
</phone>
</contact>
<name>Halley</name>
</user>
Where as my JSON looks a bit different.
{
"User" : {
"name" : "Halley",
"contact" : {
"contact" : {
"mobile" : "8971829749"
}
}
}
}
The root element user, and phone is not at all present in my sub JSON structure.
While JAXB is honouring the XMLRootElement annotation, Jackson is not. Any idea why and how I can rectify this?
I need to generate JSON and XML from the same entity classes.
you can use
#JsonRootName as class level annotation
and ObjectMapper to configure serialization to use root element.
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
Using JsonRootName is optional unless you want to have different element name than XML.
As Jackson is ignoring the element name provided via #XmlRootElement, the Jackson annotations #JsonTypeInfo and #JsonSubTypes should be used to specify which ContactInfo type is Address or Phone. See https://stackoverflow.com/a/6543330/6911095 for an example.

Reading attribute of a node in XML using itemReader Spring Batch

I have an xml below
<?xml version="1.0" encoding="UTF-8"?>
<employee siteId="1">
<name>john</name>
<age>36</age>
</employee>
I'd like to get the value of siteId (attribute value) using itemReader. I'm able to successfully read name and age child elements. I don't know how to get the value of siteId. Please help. Thanks!
You can read siteId attribute value by specifying #XmlAttribute(name = "siteId") in class please find example below
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "employee")
public class Employee {
private int siteId;
private String name;
private int age;
#XmlAttribute(name = "siteId")
public int getSiteId() {
return siteId;
}
public void setSiteId(int siteId) {
this.siteId= siteId;
}
#XmlElement(name = "age")
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

JAXB - change property name without changing variable name in class

So I have code like this:
#XmlRootElement(name = "person")
#XmlType(propOrder = {"name", "secondName"})
public class Person {
private String name;
private String secondName;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
public String getSecondName() {
return secondName;
}
}
And when I want to create XML file it makes me:
<person>
<name>John</name>
<secondName>Smith</secondName>
</person>
Is it any way to make in xml file <second-name> instead of <secondName> without changing in class on private String second-name?
Problem solved. I should just do this:
#XmlElement(name="second-name")
public String getSecondName() {
return secondName;
}

how create xml from java object using jaxb

How can i create following type xml in java using jaxb
<myInfo>
<firstName>MyfirstName</firstName>
<lastName>MyLstNme</lastName>
<contactList>
<contact>
<id>001</id>
<name>name1</name>
<contact/>
<contact>
<id>002</id>
<name>name2</name>
<contact/>
<contact>
<id>003</id>
<name>name3</name>
<contact/>
</ContactList>
</myInfo>
Bean Classes are..
#XmlRootElement(name = "myInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class MyInfo {
#XmlElement(name = "firstName")
public String firstName;
#XmlElement(name = "lastName")
public String lastName;
#XmlElement(name = "contactList")
public ContactList contactList;
...getter setter
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "contactList")
public class ContactList {
#XmlElement(name = "contact", type = Contact.class)
public List<Contact> list = new ArrayList<Contact>();
public ContactList() {
}
public ContactList(List<Contact> list) {
this.list = list;
}
...getter setter
}
#XmlRootElement(name = "Contact")
public class Contact {
#XmlElement(name = "id")
public String id;
#XmlElement(name = "name")
public String name;
...getter setter
And Exception
objData ToXML 2 counts of IllegalAnnotationExceptions
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
==
Class has two properties of the same name "id"
this problem is related to the following location:
at public java.lang.String java8javafx8.Contact.getId()
at java8javafx8.Contact
at public java.util.List java8javafx8.ContactList.list
at java8javafx8.ContactList
at public java8javafx8.ContactList java8javafx8.MyInfo.contactList
at java8javafx8.MyInfo
this problem is related to the following location:
at public java.lang.String java8javafx8.Contact.id
at java8javafx8.Contact
at public java.util.List java8javafx8.ContactList.list
at java8javafx8.ContactList
at public java8javafx8.ContactList java8javafx8.MyInfo.contactList
at java8javafx8.MyInfo
Class has two properties of the same name "name"
this problem is related to the following location:
at public java.lang.String java8javafx8.Contact.getName()
at java8javafx8.Contact
at public java.util.List java8javafx8.ContactList.list
at java8javafx8.ContactList
at public java8javafx8.ContactList java8javafx8.MyInfo.contactList
at java8javafx8.MyInfo
this problem is related to the following location:
at public java.lang.String java8javafx8.Contact.name
at java8javafx8.Contact
at public java.util.List java8javafx8.ContactList.list
at java8javafx8.ContactList
at public java8javafx8.ContactList java8javafx8.MyInfo.contactList
at java8javafx8.MyInfo
How create Bean Class and Bean List Class??
Ok hear you go:
Make one class call MyInfo as:
#XmlRootElement(name="myInfo")
public class MyInfo {
private String firstName;
private String lastName;
private List<Contact> contactList = new ArrayList<Contact>(0);
public MyInfo(){}
public MyInfo(String fName, String lName){
this.firstName = fName;
this.lastName = lName;
}
#XmlElement(name = "firstName")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#XmlElement(name="lastName")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<Contact> getContactList() {
return contactList;
}
#XmlElement(name = "contactList")
public void setContactList(List<Contact> contactList) {
this.contactList = contactList;
}
}
write another class called Contact as:
public class Contact {
private int id;
private String name;
public Contact(){}
public Contact(int id, String name){
this.id = id;
this.name = name;
}
#XmlElement(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Marshell it with JAXB (create XML) as:
public class Test {
public static void main(String[] args){
Contact c1 = new Contact(1, "first");
Contact c2 = new Contact(2, "second");
MyInfo info = new MyInfo("Shekhar", "Khairnar");
info.getContactList().add(c1);
info.getContactList().add(c2);
try {
JAXBContext jaxbContext = JAXBContext.newInstance(MyInfo.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(info, System.out);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
In above eg. I just print the xml output on console you can write in a file also.
out put will be:
<myInfo>
<firstName>Shekhar</firstName>
<lastName>Khairnar</lastName>
<contactList>
<id>1</id>
<name>first</name>
</contactList>
<contactList>
<id>2</id>
<name>second</name>
</contactList>
You can do the following:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class MyInfo {
private String firstName;
private String lastName;
#XmlElementWrapper
#XmlElement(name="contact")
private List<Contact> contactList;
// getters & setters
}
Things to note:
JAXB is configuration by exception so you only need to annotate where you want the XML representation to differ from the default.
By default JAXB treats public fields and properties as mapped. If you want to treat only fields as mapped you should specify #XmlAccessorType(XmlAccessType.FIELD).
The mapped fields can be private.
#XmlElementWrapper is used to add a grouping element to a collection.
When #XmlElement is used on a collection it applies to each item in the collection.

Categories

Resources