Jaxb custom element from two fields of an object - java

Is there a way with jaxb to create a custom element from two fields from an object?
Here's an example of what I have and what I want. I realize I could extract the fields into a seperate annotated class, but I'm curious of theres a way to do something similar to this.
#XmlRootElement()
public class Foo {
public String bar
public String baz
}
Expected output xml:
<foo>
<customElement bar="barValue">bazValue</customElement>
</foo>
Thanks!

class for foo
#XmlRootElement()
public class Foo {
private customElement CustomElement;
public CustomElement getCustomElement(){
return customElement;
}
#XmlElement
public void setCustomElement(CustomElement customElement){
this.customElement = customElement;
}
}
class for custom element
#XmlAccessorType(XmlAccessType.FIELD)
public class CustomElement {
#XmlAttribute
private String bar;
#XmlValue
private String baz
// set getters and setters
}

Related

JAXB how to nest several objects?

I've been trying to search how to do this but I haven't found an answer to my exact requirements:
Let's say we had this 3 classes:
public class Main {
public ArrayList<MyFirstClass> myFirstClass;
}
class MyFirstClass {
public int num;
public MySecondClass mySecondClass;
}
class MySecondClass {
public String otherStr;
public MyThirdClass myThirdClass;
}
class MyThirdClass {
public int otherNum;
}
I wanto to be able to read these XML with the unmarshaller:
<Main>
<MyFirstClasses>
<MyFirstClass>
<num>1</num>
<MySecondClass>
<str>Hello</str>
<MyThirdClass>
<otherNum>2</otherNum>
</MyThirdClass>
</MySecondClass>
</MyFirstClass>
<MyFirstClasses>
</Main>
Where I'm basically able to set the variables that are objects (MySecond/Third Class).
I know I can use #XMLRootElement and then #XmlElementWrapper(name="aName") and #XmlElement(name="aName") to do the
<Main>
<MyFirstClasses>
<MyFirstClass>
<num>1</num>
</MyFirstClass>
<MyFirstClasses>
</Main>
But how can I then nest the MySecondClass inside MyFirstClass so I can set it's values, because otherwise the FirstClassObject will have a MySecondClass which has null values.
Thanks in advance!
The problem is that your xml does not match your POJOs. You can use annotations to fix this(renaming fields would also work). Try this:
#XmlRootElement(name = "Main")
public class Main {
#XmlElementWrapper(name = "MyFirstClasses")
#XmlElement(name = "MyFirstClass")
private List<MyFirstClass> myFirstClass;
}
Then FirstClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MyFirstClass {
private int num;
#XmlElement(name = "MySecondClass")
private MySecondClass mySecondClass;
}
And MySecondClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MySecondClass {
private String str;
#XmlElement(name = "MyThirdClass")
private MyThirdClass myThirdClass;
}
Finally MyThirdClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MyThirdClass {
public int otherNum;
}

How to pass a variable from 2 different POJOs?

I got 2 POJOs that are being passed to a HttpEntity and converted to json.
Before passing them i need a variable which is in both of the POJOs with different names because of the needs of the API so i cant change them.
What is the best way without casting and in terms of OOP also within the POJO definition like mentioned in Wikipedia?
Abstract pojo
public abstract class Pojo{
//some common variables
//setter getters
}
PojoOne
public class PojoOne extends Pojo{
private String id;
//setter getter for id
}
PojoTwo
public class PojoTwo extends Pojo{
private String identifier;
// setter getter for identifier
}
Class that
public class SomeOtherClass {
public void getIdForUse(Pojo pojo){
String s = pojo. // How should this be to have ability to get both id and identifier
}
}
Add a common method to the common superclass:
public abstract class Pojo {
public abstract String getId();
// some common variables
// setter getters
}
public class PojoOne extends Pojo {
private String id;
#Override
public String getId() {
return id;
}
//setter for id
}
public class PojoTwo extends Pojo {
private String identifier;
// setter getter for identifier
#Override
public String getId() {
return identifier;
}
}

Repeat json field with different name

i have a POJO mapped which i serialize using Jackson
public class Foo{
private String bar;
// public setter and getter for bar
}
it serializes to
{bar:"value"}
is there a jackson annotation to get another field in the JSON with the same value but with a different alias name, something like
{bar:"value", another_bar:"value"}
This should work for duplicating the value, though why you'd want to waste space like that is puzzling:
public class Foo {
private String bar;
#JsonProperty
public String getBar() {
return this.bar;
}
public void setBar(String bar) {
this.bar = bar;
}
#JsonProperty("another_bar")
public String getAnotherBar() {
return this.bar;
}
}

JAXB abstract class with #XmlTransient

I'm using JAXB to unmarshal some xml into an object(s).
I have a class which inherit from an abstract class. I've marked the abstract class as #XmlTransient. Then using XMLType PropOrder I can access the properties in the abstract class like so:
#XmlType( propOrder = { "id"...
Cool. Problem is sometimes it isn't an element that I want to access but rather an attribute. Normally you would define such a property using #XMLAttribute to indicate the value is stored in an xml attribute and not an element. But given the fact that I've already used XMLTransient on the abstract class where 'id' is defined, JAXB complains when I try to mark the field as #XMLAttribute.
JAXB is complaining that I'm trying to access/return two fields of with the same name.
Can anyone please point me in the right direction? I'm building for GAE so I dn't really want to use any other libraries.
Thanks in advance!
Below are a couple of things you can do:
Java Model
Foo
You can annotate the property on the parent class with #XmlAttribute.
import javax.xml.bind.annotation.*;
#XmlTransient
public class Foo {
private String att1;
private String att2;
#XmlAttribute
public String getAtt1() {
return att1;
}
public void setAtt1(String att1) {
this.att1 = att1;
}
public String getAtt2() {
return att2;
}
public void setAtt2(String att2) {
this.att2 = att2;
}
}
Bar
You can override the property on the subclass and annotate it with #XmlAttribute.
import javax.xml.bind.annotation.*;
#XmlRootElement
public class Bar extends Foo {
#Override
#XmlAttribute
public String getAtt2() {
return super.getAtt2();
}
#Override
public void setAtt2(String att2) {
super.setAtt2(att2);
}
}
Demo Code
Demo
Here is some demo code you can run to show that everything works.
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Bar.class);
Bar bar = new Bar();
bar.setAtt1("a");
bar.setAtt2("b");
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(bar, System.out);
}
}
Output
Below is the output from running the demo code:
<?xml version="1.0" encoding="UTF-8"?>
<bar att1="a" att2="b"/>

jaxb: inline elements

Given:
#XmlRootElement(name = "foo")
class Foo {
public Bar getBar() {...}
}
class Bar {
#XmlElement(name = "string")
public String getString() {return "hello";}
}
How do I annotate so the XML will be:
<foo>
<string>hello</string>
</foo>
You could do the following leveraging the #XmlValue annotation.
Foo
#XmlRootElement
class Foo {
#XmlElement(name="string")
public Bar getBar() {...}
}
Bar
class Bar {
#XmlValue
public String getString() {return "hello";}
}
For More Information
http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html
You probably need to use #XmlSeeAlso annotation on top of your class.
You can use #XmlSeeAlso annotation when you want another Entity bean to be included in the XML output. Can you try this in your Foo class
#XmlRootElement(name = "foo")
#XmlSeeAlso(Bar.class)
class Foo {
public Bar getBar() {...}
}
Update1:
For your comment to remove the bar tag in the XML try using EclipseLink JAXB (MOXy)'s. #XmlPath will solve your issue.
#XmlRootElement(name = "foo")
#XmlSeeAlso(Bar.class)
class Foo {
#XmlPath(".")
public Bar getBar() {...}
}
Refer here for more details.
I'm not sure you can to eliminate the tag bar from resulting XML:
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html#wp148576

Categories