Making #XmlTransient annotation just for serializing? - java

I use Spring and Apache CXF for my project that implements java Web Services with first-code style.
I have a variable as defined:
#XmlTransient
public String word;
So that variable doesn't map to an attribute at XML.
However I want it to be ignored to mapping XML element at serialization but not at deserialization.
How can I do that?

I don't think you can achieve that with #XmlTransient. An option would be to use MOXy to marshal using one schema and unmarshal using another schema. You can find a great example here.
A simple but less elegant workaround would be something like this:
#XmlTransient
public String word;
public void setDeserializedWord(String word) {
this.word = word;
}
#XmlElement(name="word")
public String getDeserializedWord() {
return null;
}

Related

Java spring. Annotations for tricky serialization to json and xml

I'm trying to rewrite some API serialization from custom mappers to annotation-based style and faced with one hard mapping (which was earlier custom-serialized to json and xml separately) that I can not "translate" to. (Serialization is made with Jackson.)
In the POJO we have a collection, e.g.
class Data {
Set<Integer> tags;
}
which should be serialized in xml like:
<tags>
<tag id="1"/>
<tag id="2"/>
</tags>
and in json like:
{
"tags":[1,2]
}
Strait method with
#XmlElementWrapper(name="tags")
#XmlElement(name="tag")
gives good json, but incorrect xml like
<root>
<tags>
<tag>1<tag/>
<tag>2<tag/>
</tags>
</root>
cause there is no attribute specification.
I tried to wrap a bit with:
class Data{
#XmlElementWrapper(name="tags")
#XmlElement(name="tag")
Set<Tag> tags;
}
class Tag{
#XmlAttribute(name="id")
Integer id;
}
But this produces unwanted key in json format, like:
"tags":[
{"tag":{"id":1}},
{"tag":{"id":2}}
]
Ok, then. I tried to specify custom json serializer(implementing JsonSerializer and injecting with #JsonSerialize(using = ...) ), but seems it also affects xml "render".
Is it possible to do the trick with annotations only? Or mb is it possible somehow use default json serialization and custom xml serializtaion for some class? .e.g.
use custom xml serialization only for Reasons class in such way
class Data {
#XmlElement("tags")
Reasons tags;
}
but let all surrounding data be "render" with general strategy.
Simply create a getter annotated with #JsonValue will tell Jackson to produce a single value, without any field name.
This mapping:
#XmlRootElement
public class Data{
public Set<Tag> tags;
}
public class Tag{
#XmlAttribute
public Integer id;
#JsonValue
public Integer getId() {
return id;
}
}
Will then produce:
{"tags":[2,1]}
And:
<data><tags id="2"/><tags id="1"/></data>
PS: You're using JAXB annotations, i don't think Jackson will honor them.
To get the XML result above, you need to use JAXB:
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(Data.class, Tag.class);
Marshaller m = context.createMarshaller();
m.marshal(value, writer);
System.out.println(writer.getBuffer().toString());
As a final note, i'm not super fan of using a single mapping for multiple representations. It's probably good for simple stuff, but if your code grows more complex than this, i strongly suggest you create two sets of classes (one for XML mapping and one for JSON), maybe with a common interface.

How to dynamically Create Java Objects from XML/XSD that contain custom annotations used by a 3rd party library

My goal is to take a XML and/or XSD file and dynamically create a Java object that contains costume annotations and load it into the JVM. A 3rd party library would then look for those objects containing that annotation and perform some function to it. example output of what the java object would look like is as follows
import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.variable.PlanningVariable;
#PlanningEntity
public class NameAssignment extends ResourceAssignment{
private String name;
#PlanningVariable(valueRangeProviderRefs = { "PlannerCountRange" })
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The part i'm struggling with is generating the annotation fields #PlanningEntity and #PlanningVariable(valueRangeProviderRefs = { "PlannerCountRange" }) before, during or after the unmarshalling of the XML.
I've been trying to figure it out with JAXB, Dynamic JAXB, Dynamic JAXB, JavaAssist(for byte code manipulation), JCypher, and XJC(Just for compiling the classes). I even thought about dumping Java altogether and using Groovy.
I'm starting to feel like I'm over complicating this and need some guidance. This is a "from scratch" project so I have zero constraints on how I implement it.
Any Help would be greatly appreciated.
With jaxb2-annotate-plugin you may inject any static annotations into generated code just provide binding.
Please look for answer Custom annotation with jaxb2-annotate-plugin and XJC tool for details and examples how to use it.

Use JAXB Annotation With Value

When generating XML using JAXB annotations, I know it's not possible to use #XmlElement(name="City") & #XmlValue on the same Java member because they are mutually exclusive. Is it possible to #XmlElement to produce an XML tag with a value at the same time? Not being able to do this causes a ton of objects to be created and seems to be overkill.
Java Code
....
#XmlElement(name="City")
#XmlValue <---- I'm wanting to do this but I'm limited by the API
private String city;
Expected Output
....
<City>some value here</City>
....
We can try to achieve the same using another type which uses #XmlValue annotation.
Below is what you can try -
#XmlRootElement(name="CityRoot")
#XmlType(name="CityRootType")
public class CityRoot {
#XmlElement(name="City")
public CityName s;
}
CityName definition as below
public class CityName {
#XmlValue
String name;
}
Now, feed these two files to schemagen to have the .xsd file generated and using that generate .xml file to verify.
Below is how generated xml file looks like when I generated it -
<?xml version="1.0" encoding="UTF-8"?>
<CityRoot>
<City>SomeCityName</City>
</CityRoot>
If you want to have an element with simple text, the only annotation you need is the #XmlElement annotation. If the type of a field is String, JAXB generates an xml element with the value of the String as the value of the element.
The only thing you need is this:
#XmlElement(name="City")
private String city;

Marshal an object as one of its properties with Jackson (as for value objects i.e primitive types wrappers)

EDIT: Previous answer does not work (it stills create a nested object)
I'm using Jersey and Jackson.
I got a class like
#XmlAccessorType(XmlAccessType.NONE)
public class Name {
private String value;
#XmlValue
public String getValue(){...}
public void setValue(String value){...}
}
used as in
public class Person{
#XmlElement(name = "IDName")
public Name getName(){...}
}
I'd like to marshal Name object as the value of it's identity property.
How can I achieve that?
<Person>
<IDName>foo</IDName>
</Person>
instead of
<Person>
<IDName>
<Value>foo</Value>
</IDName>
</Person>
I'd tried both to indicate in Person that Name object should be marshalled as itself.getValue() and either to indicate within Name class to marshal without any element wrapper (its fields directly) with no luck.
A possible solution is replacing #XmlValue annotation with Jackson's #JsonValue to make it work (tested).
I infer from http://wiki.fasterxml.com/JacksonJAXBAnnotations that it can be the only solution for now
According to this the official documentation
#javax.xml.bind.annotation.XmlValue
The field/property to which this annotation is applied will be named "value".
So maybe it's limited by design. Any better answer, specially if using JAXB annotations alone, will be much appreciated

What is the Jaxb equivalent of a Text node value?

I am looking to convert a class that looks like this ...
public class Amenity {
public String id;
public String value;
}
into the following XML using JaxB annotations:
<amenity id="id-string-here">value-string-here</amenity>
Does anyone know what annotation to use on the value member variable to accomplish this? The closest I've gotten so far is:
#XmlRootElement
public class Amenity {
#XmlAttribute
public String id;
#XmlElement
public String value;
}
Unfortunately this approach doesn't allow me to specify that the value member variable should not be rendered as its own tag <value></value>.
I'm not 100% sure about this, but try to use an #XmlValue annotation instead of #XmlElement.
It looks like the question was referring to text nodes not CDATA nodes, but here is a link on how EclipseLink JAXB (MOXy) handles CDATA:
http://bdoughan.blogspot.com/2010/07/cdata-cdata-run-run-data-run.html
This documentation writes:
Q. How can I cause the Marshaller to generate CDATA blocks?
A. This functionality is not available from JAXB directly, but you can configure an Apache Xerces-J XMLSerializer to produce CDATA blocks. Please review the JaxbCDATASample.java sample app for more detail.
(btw, this does not answer your particular question, but since the question title is misleading, and this is the first google result for jaxb CDATA, I'm answering a bit different question)
JAXB does not support marshaling/marshaling to/from CDATA xml types.

Categories