Due to old project decisions, I work on a project that uses Jersey to connect to services that return XML data. Sometimes I could create the bean/pojo/whatever annotated with XmlRootElement and use webTarget.get(MyPojo.class)
However, if I try to do what I would do with, say, Jackson, and do webTarget.get(Map.class) I get the following error:
MessageBodyReader not found for media type=text/xml, type=interface java.util.Map, genericType=interface java.util.Map.
My case is, I have a XML that can have arbitrary fields whithin, so the ideal way for me to read it is to read a Map. Is there any way I can do that without having to rely in other libraries? I don't need to serialize data, only deserialize responses from the web services I connect to.
Found the answer, and it's kinda depressing.
According to the Unofficial JAXB Guide, you can't use a Map as a root element, unless you do a very ugly hack, described there. So, the solutions are:
Read as a String, and use Jackson to read a Map from the string.
Do the ugly hack.
Describe part of the schema in a bean, but the part that can have variable fields can be deserialized to a Map.
Related
What serializer is Entity.json(T entity) using to serialize/deserialize objects? Is it somehow possible to use a custom serializer?
In my case the serialization is wrong because my object contains fields with the Guava Optional data type and absent values are returned as {"present":false} instead of null.
The JSON serializer isn't specified by JAX-RS, it depends on your configuration. For example, Jersey JAX-RS allows several (https://jersey.java.net/documentation/latest/media.html), including
MOXy
Java API for JSON Processing (JSON-P)
Jackson
Jettison
But a better solution is not to use Optional (either Guava or Java 8) for fields. See http://blog.joda.org/2014/11/optional-in-java-se-8.html
My only fear is that Optional will be overused. Please focus on using
it as a return type (from methods that perform some useful piece of
functionality) Please don't use it as the field of a Java-Bean.
Not directly solving your problem. I suggest you use Googles Gson as a parser. It is very flexible and configurable.
Tutorial
It also skips blank fields so the json size is not too large.
I am using Axis to call a SOAP-based web service. I'm then trying to serialize the returned remote object as JSON, using the Google Gson library.
The serialization to JSON fails, with Gson complaining that "there are multiple elements with the name __equalsCalc()).
When I inspect the returned object in my IDE (Eclipse), I can see that this is true -- the returned object has three members called __equalsCalc() and another three called __hashCode.
I know from looking around that these are added by WSDL2Java (I think) in order to avoid recursion. My question is, why are there THREE of each? And how can I get the serializer to ignore these? They're not actually part of the object's definition (it's called a RemoteProject, for reference). Can I do something hackish like cast the RemoteProject to a RemoteProject to get it to drop those members?
This turns out to be not too hard to solve. I have multiple copies of the same instance var because the class being serialized is shadowing fields of the same name from superclasses. Since I don't care about these fields, the best approach in Gson is to write a custom ExckusionStrategy which can selectively ignore fields based on their name:
http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/ExclusionStrategy.html
I don't know GSon.
With Jackson, you can annotate properties (i.e - fields that have getters/setters according to Java bean convention) with #JsonIgnore.
This way you can prevent issues like recursion/no matching setter or getter and so on...
Try to find out if you have the same at GSon or use Jackson.
We have a Java List of objects which is marshalled via JSON which is created by Jersey.
The List is called "rows". When there is data we have:
{"records":"1","page":"1","total":"1","rows":[{"id":"692334","cell":["ECS","D","201009","","0","ABCD","11","11","","201009"]}]}
When there is no data we have:
{"page":0,"records":0,"total":0}
How can we make Jersey include the rows field even if the List has a size of 0? What we want is:
{"page":0,"records":0,"total":0,"rows":[]}
Note that we are already using a JAXB ContextResolver to ensure the JSON is correct for a single row. Not sure if we can configure this resolver to solve our problem.
Use Jackson JAX-RS provider instead of alternatives (badgerfish/jettison), which does not do XML-to-JSON conversion. Missing array is most likely due to this conversion. There are multiple ways to configure this (jersey mailing list should have a few), and latest versions may expose it directly via Jersey API.
Maybe this helps you:
http://jersey.java.net/nonav/documentation/latest/json.html#d4e903
seems that some array problems can be solved by using something like this:
JSONConfiguration.mapped().arrays("yourArrayName").build()
At least it solves the issue, when the list contains only 1 item it's also formated as an JSON array.
I managed to solve JSON array "bug" in Jersey json library. Secret ingredient is previusly mentioned JSONConfiguration and ContextResolver magic. See my following post it has a full code example, customized ContextResolver and rest Application class might be somewhat fuzzy logic in first look.
How to serialize Java primitives using Jersey REST
json array for zero or single-element Java lists
primitive integer or boolean fields without quotation chars
I'm getting "JSONRpcClientException: ... circular reference." when serializing my domain objects with JSON. (using jsonrpc1.0).
I'd like to maintain the domain as it is, but need to get JSON-RPC working so I wonder if there is any solution to avoid or skip some fields of a Java class (those circulars) of being serialized to JSON as it is described here for .NET.
Is it posible to use something like ScriptIgnore tags in Java to reach this?
I am writing the service to implement the audit in our application wherein users can view the status of a particular entity before and after any modification and should also be able to roll it back. We have decided to store the XML Serialized object in the databse in XML_TYPE column.
I am new to serialization, I don't know how to achieve the same, any changes needs to be done to the object to be serialized or do we need to have any mapping XML. Can someone please suggest some good libraries, I understand there are lot of those available in the market like JAXB, JIBX, JABX, XStream and etc. Which one would be good and how to use it.
Any help is highly appreciated.
Regards,
Ravi.
Of course, the best for entities is having POJO's (Plain Old Java Objects). No strange properties, references or methods. It simplifies serializing and keeps your model objects neutral from frameworks and strange layers like persistence, UI, remote-access and so on.
XStream: simplicity
I'd suggest using XStream library for serializing. It tries to be the simplest way to serialize and deserialize objects to XML.
You should think searialization this way:
indicate what class is the object
try to serialize each property
So, these are the two problems to resolve in serializing. XStream lets you create a serializer (XStream class), (OPTIONALLY) indicate what tag name use for each class and (OPTIONALLY) indicate the aliases for properties.
So if you have something like:
package pack;
Person
+ mom: Person
+ dad: Person
it will write with no configuration:
<pack.Person>
<mom>
<pack.Person>
...
</pack.Person>
</mom>
<dad>
<pack.Person>
...
</pack.Person>
</dad>
</pack.Person>
But if you tell it to map package.Person to it will use that tag. You can tell it to write property "mom" as "mother" and things like that.
XStream xs = new XStream();
xs.alias("person", Person.class);
xs.aliasAttribute(Person.class, "mom", "mother");
References
XStream also lets you indicate what kind of references you want:
no references: serialize an object
each time it founds it in the object
tree
absolute references: the second time
an object is found it saves a
reference using the absolute path of
the first instance
(/people/person[4]/teacher)
relative references: the same, but
using a relative reference from this
point (../../person[4]/teacher)
JAXB is the standard. In the simplest (and most common case) you just annotate your entities with JAXB annotations, and use a Marshaller to marshal the object to XML.
You can use either Sun's reference implementation, or Apache JaxMe.
XStream is a good alternative as far as I know, although I haven't used it.