Converting xml string to Object class using jackson - java

Can someone please help in deserializing xml string : List<A> to Object.class using jackson in java.Xml looks like :
<list> <A><id>1</id><name>Jeff</name> <id>2</id><name>John</name> </A>
It returns a HashMap object if I convert it to Object.class . I have created a utility function XMLToObject which returns Object class. This will be typcasted on the caller function end to get the required type of Object.
public Object XMLtoObject(String xml){
return mapper.readValue(xml,Object.class)
}
But if I use List.class in place of Object.class it deserializes it to list of hashmaps.
public Object XMLtoObject(String xml){
return mapper.readValue(xml,List.class)
}
I am looking a way to convert it into Object.class which I can typecast on caller function . Is that possible in jackson ? I know we can do it through xstream

The problem with List.class is that it doesn't have any information about its elements. You need one of the overloaded readValue methods. For instance, using TypeReference:
return mapper.readValue(xml, new TypeReference<List<Object>>() {});
This creates an anonymous sub class of TypeReference, from which the complete generic type (List<Object>) can be read by Jackson. The result should therefore be a List<Object> instead of a List<HashMap>.

Related

What is JSON equivalent to #XmlAnyElement?

I'm using jackson and I have a problem with the method returning the Object object. This means that different classes can be passed in .json file and I want to parse them to the corresponding object from my project.
#XmlAnyElement (lax = true)
public Object getEntity() {
return this.entity;
}
I always get LinkedHashMap in return since JSON isn't sure what object should it expect.
Is it possible to annotate the method with the list of expected class names?
Is it possible to annotate the method with the list of expected objects that should be returned?

How do I parse a generic class parameter from JSON in Scala?

I have a generic getter trait
trait Getter[A] {
def get: A
}
and I would like to parse JSON into a List of objects implementing this trait. Two such implementations:
case class CoalesceGetter[A](getters: List[Getter[String]]) extends Getter[A] {
override def get: A = getters.map(_.get).find(_ != null).orNull
}
case class AsnGetter(ipGetter: Getter[String]) extends Getter[Long] {
override def get: Long = 99L // dummy function
}
I would like to parse JSON into the correct Getter class based upon a property called function which corresponds to the class and type which corresponds to the generic type in the case of getters which need a generic (both properties are strings in the json blob I'm parsing). I've looked at custom serializers for json4s but don't see how to work with generics. Any help is appreciated!
First of all, I don't think it is a good idea to jsonify classes with type argument. I think it is a better design to define non-typed (case) classes that are direct equivalent of your json object, and use standard read/write json as provided by many libraries.
But then, to answer your question, I'd like to return another question: how would you do it "manually"?
I.e. how would you write and read different CoalesceGetter[A] with different A?
Here is a proposition: put the type arg in a json field:
"ofInt": {"type-arg":"Int", "getters":[ ... list of getters in json ...]},
"ofDouble":{"type-arg":"Double", "getters":[ ... list of getters in json ...]}
Now, if you'd write the reader, how would you instantiate the 2 ofInt and ofDouble, knowing the type-arg "Int" and "Double" (which are string!).
I see 2 solutions:
1) Either you have a hard-coded map of arg-type string => actual scala type
argType match{
case "Int" => new CoalesceGetter[Int](...)
case "Double" => new CoalesceGetter[Double](...)
}
2) Or you store and read a generalized type as string value in the arg-type string, such as the java Class.forName (see [https://stackoverflow.com/a/7495850/1206998] for example). But this is a really really bad idea IMHO.
(note: if you want to serialize any object just to reload it later or on another computer, don't use json but dedicated serialization such as the Java Serialization or kryo that is used by spark)

How JSON deserialize Array?

I am using fasterxml.jackson. I am confused about readValue(). Here is my question.
I know jackson deserialize normal JavaBean and Collection in two different ways.
For JavaBean, we can pass MyBean.class or new TypeReference<MyBean> to readValue(). For Collections, we must pass new TypeReference<List<MyBean>>. That is because TypeReference saves the type erased by Collection. Am I right? :)
Now I am confused. If MyBean contains a list, then I can still pass MyBean.class and it works. How does jackson do that?
public class MyBean {
String str;
List<String> strList;
}
You are passing MyBean.class as the second argument to readValue() and Jackson can get the type from this through reflection. I'd guess Jackson does something like this :
MyBean.class.getDeclaredField("strList").getGenericType();
which will result in a type of java.util.List<java.lang.String>.
Note that you have a non generic class MyBean containing a List<String>. If you had for instance:
class MyGenBean<T> {
List<T> list;
}
then
MyGenBean.class.getDeclaredField("list").getGenericType();
would return java.util.List<T> and you would need a TypeReference.

How to determine class of object from GSON parse?

I am parsing JSON string from a byte-array and casting it as an object.
How do I determine the class of the object?
Object objDeserialized = gson.fromJson(jsonFromString, Object.class);
//It could be type Message or RoomDetail
gson.fromJson(jsonFromString, Object.class);
In general, this won't work because of Object.class. Gson prohibits overriding the Object class deserialization and uses ObjectTypeAdapter (see the primary Gson constructor as of Gson 2.8.0 and probably much earlier):
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);
// user's type adapters
factories.addAll(typeAdapterFactories);
If you want to use Object.class, you have to cast the result to either a primitive wrapper, null, or a List<E> or Map<K,V> -- and make some sort of analysis yourself. The rationale behind it is that you must know the result class in advance to make sure you're getting a proper deserialized object.
The best thing you can do here is making your custom parent super-type (does not really matter if it's a class or an interface), say class Message extends Base and class RoomDetail extends Base, and then registering a JsonDeserializer<Base> implementation to a GsonBuilder which can attempt to detect the real type of the Base instance. After that you can do:
gson.fromJson(jsonSource, Base.class);
See more:
Polymorphic objects deserialization:
How to parse dynamic json in android with retrofit 2 using annotations
How do I parse a nested JSON array of object with a custom Gson deserializer?
Json response parser for Array or Object
Google Gson extras, never been published as artifacts, but may be an inspiration point for you:
https://github.com/google/gson/blob/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java
If you do not know the type of the JSON you want to parse you could use the JsonParser from the Gson lib to parse the JSON instead of the Gson class directly. e.g.
JsonParser parser = new JsonParser(jsonFromString);
JsonObject obj = parser.parse().getAsJsonObject();
You could then look at the properties of the JsonObject you have created to see what it is. e.g.
if (obj.has("somePropertyNameIKnownIsAMemberOfRoomDetail")) {
RoomDetail roomDetail = gson.fromJson(jsonFromString, RoomDetail.class);
} else {
Message message = gson.fromJson(jsonFromString, Message.class);
}

Gson toJson method returning empty

I am attempting to take List of objects of type SearchResultView that I have and convert it to a Json string using Googles Gson library, v 2.3.
The following is the relevant code(which I wrote by mimiking the documentation https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/Gson.html#getAdapter-com.google.gson.reflect.TypeToken-
Type typeResults = new TypeToken<List<SearchResultView>>(){}.getType();
String resultsJSON = (new Gson()).toJson(resultsView.getResults(), typeResults);
System.out.println(resultsJSON); //To test output.
The printline prints the following:
[{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}...
I have already verified that
resultsView.getResults()
returns an object of type
List<SearchResultView>
and that the list itself is not null and nonempty. What could be the issue here?
EDIT(Upon request): SearchResultView is an interface of all 'get' and 'has' methods. The object in the list is just a bunch of objects which implement that interface.

Categories