Cast to class from JSONObject - java

I got JSONObject from service response.
Well in case of an error I need to cast it to one of the error classes.
Json is something like
{"message":"This means that the userID is not valid.","name":"UserNotFoundException"}
where name can be any of the exceptions in model package
Can I do this?
Class ex = Class.forName("com.myapp.model.Exceptions." + jsonObject.getString("name"));
How can I cast ex to UserNotFoundException class so I can use its methods i.e.
ex.doSomething()

If you really need to do this (although this is something that is usually done very rarely), take a look at reflection: Java how to instantiate a class from string

You can use GSON. it easily serializes and de-serializes json data..
For Reference -- > https://code.google.com/p/google-gson/

you aren't actually casting anything in your code, you are retrieving a class instance using a naming convention of your own. You'll need to create an instance of that exception class later on using the message from your JSON object.
Casting is a complete different thing, to get some understanding you can look at this answer.
The thing is, you can't cast a JSON object to a Java class, the same way you can't cast a DOM tree to a Java object tree. What you can do (and everyone does) is to marshal/unmarshal the JSON object to a Java class. This means, creating instances of the Java classes that match the JSON object structure and then map the attributes of that Java class with the attributes of the JSON object.
So, in your code it would look like:
Class ex = Class.forName("com.myapp.model.Exceptions." + jsonObject.getString("name"));
Constructor cons = ex.getConstructor(String.class);
UserNotFouncException unfe = (UserNotFoundException) cons.newInstance(jsonObject.getString("message")); // here is where actual casting is happening
Note: please, be aware that above code may throw exceptions that you need to guard for.

Related

Create POJO Model with dynamic object value

I have a 3 object value from JSON, and the second object is dynamic value, i.e. it can be an array or an object. So it look like this one :
{
obj1 : {....},
dynamicObj2 : {....}, // it can be object or array
obj3 : {....}
}
So, my question is how can this be achieved in the POJO class? I am using GSON for this case. And it will be implemented at Android end and I am using retrofit for the networking library. Any suggestion for POJO class? Or I must use manual String object and parsing one by one?
If the Object it can be is of the same kind as the elements in the Array just make it always an array in your Java Class. if not then you will need to use the Object class and cast it to the appropriate type you want later.
You can also automatically generate a POJO using this tool: http://www.jsonschema2pojo.org/
You can even make it serializable, parcelable, and so on. Just check Gson and preview to see if the class is in your liking.

Java JSON deserialization without predefining everything

I realize this has probably been asked a hundred times but I have searched a lot and can't find specifically what I'm looking for.
Here is what I'd like. Given a string data, I'd like to deserialize into an object obj that doesn't have all the fields predefined. I'd like to just be able to ask for the fields I want such as obj.getString("stringFieldName") or obj.getInt("intFieldName"). I already have gson being used for other things so if it is possible with gson that would be great although not opposed to using another library.
The 'standard' Android JSON library (since API 1) already provides such untyped access.
See JSONObject, eg. getInt:
Returns the value mapped by name if it exists and is an int or can be coerced to an int, or throws otherwise.
Unless needing the JSON mapped onto a 'native' Java collection type this is probably the simplest way to achieve the request. It doesn't require any additional libraries.
With Jackson library you can annotate data model class with
#JsonIgnoreProperties(ignoreUnknown = true)
and the jacksonconverter will just parse only these fields that you defined. Other will be ignored.
Have you tried using Retrofit from Square? It works with GSON and Java Annotations and it's super easy to set up.

simple method/extendable class to make my toString method of a POJO output json like output?

I have a number of pojos which are being used for a jersey client to be filled with the JSON data from a restful call. The client is reading in json and filling these objects using the JacksonJsonProvider. I'm not using any annotations, the variable names are equal to the json coming in.
I would like the toStrng methods for these PoJos to automatically output a representation of the json they represent, without my having to manually write each toString. Since these are basic POJO which are structured in a simlpe tree format it should be realatively easy to output these pojo as json in the toString method. In fact I know I could use reflection to do this myself in some parent/abstract class if I felt like it. However, it feels like I shouldn't have to do this by hand. Is there already some method out there that will do this for me I can use instead?
I don't insist that the output be json, though that would be preferable, but any similar method of visualizing the variables automatically without my manually writing it would be fine.
Thanks
If you use Google GSON you can serialize objects into JSON. Your toString() would then look something like:
public String toString() {
return StaticLib.GSON.toJson(this);
}
A GSON object can be shared across all objects, hence my inclusion of this mystery StaticLib class. You can find the correct name or place for that in your own project I'm sure.

Is there a way to downcast a GWT AutoBean?

I've been using AutoBeans to map JSON data coming from a non GWT-RPC Java based web service. Everything has been working so far except for one mapping.
On the server side, the Class has a property of type Map where MyAbstractParentObject is the parent class of about 15 different child classes.
When I map that to a corresponding AutoBean interface on the client I'm not able to downcast MyAbstractParentObject to its child type after it's been decoded. I looked all over the GWT docs and 'the Googles' to see if AutoBeans even has polymorphic support but couldn't get an answer either way. Interceptors and Categories don't seem to be able handle this, just methods they want to exist in the interface that aren't getters/setters.
I was attempting to do a workaround using the type field in the JSON data to create an instance of the child class but the AutoBean does not give me access to the raw JSON, even though in the debugger I can see it as a protected field called 'data'. If I try to decode the original bean it will only have the fields in the MyAbstractParentObject.
The only alternatives I can see are to:
Extend or create my own AutoBeanCodex that can properly handle the
children of MyAbstractParentObject when it decodes the JSON.
Find a way to get to the raw JSON in the MyAbstractParentObject AutoBean
and use that to create and instance of the child class on the fly.
Switch to some other JSON-GWT Serialization framework like
GWTProJSONSerializer or piriti.
Any help would be appreciated.
I know this was asked a long time ago, but I struggled to find an answer too. I realized that the AutoBeans, since they're basically just fancy wrappers for the JSON, still contain all the data for the fields of the child object you want to downcast it to. So I wrote a method like this:
public <A, B> B cast( A sourceObject, Class<B> targetClass )
{
AutoBean<A> sourceBean = AutoBeanUtils.getAutoBean( sourceObject ); // Get the corresponding AutoBean.
HasSplittable splittableBean = ( HasSplittable ) sourceBean; // Implementation (if still AbstractAutoBean) supports this interface ;)
Splittable splittable = splittableBean.getSplittable().deepCopy(); // If you don't copy it, decode() tries to be clever and returns
// the original bean!
AutoBean<B> targetBean = AutoBeanCodex.decode( typeFactory, targetClass, splittable ); // Create new AutoBean of
// the target type.
return targetBean.as(); // Get the proxy for the outside world.
}
--Where typeFactory extends AutoBeanFactory, as you can see.
It's worked well enough for me. The trickiest bit was the cast to HasSplittable, since AutoBean doesn't extend that interface, but AbstractAutoBean (which implements AutoBean) does -- and a subclass of that is what's returned by calls to getAutoBean().
You also need to copy the Splittable, otherwise AutoBeanCodex thinks, "hey, I already have an AutoBean for that Splittable! Here you go!" -- and just gives you the original. ;)
Anyway, you can cast downwards, upwards...sideways! :P
Late edit: Stumbling upon this again months later, I figured I'd add a small caveat about something Jonathan mentioned below. The method I've described here is designed to be used on an AutoBean that hasn't been modified since it was deserialized. That's because (AFAIK) there's no guarantee that any setters you call will actually update the JSON (needed for the casting). This probably isn't a big deal, since typically you'll use this when you have an incoming DTO and you want to cast it to its real type ASAP, before doing anything else with it. In our case, none of our AutoBeans even had setters, so it wasn't really an issue. ;)
After you've cast it, you can do whatever you want with the resulting bean, which is fresh out of the factory after all!
I'm not very familiar with AutoBean but you probably can use the serializer/deserializer from RestyGWT. It supports polymorphism by making use of annotation.
link to the documentation:
http://restygwt.fusesource.org/documentation/restygwt-user-guide.html#Polymorphic_Sub_Types

Interfaces are not enough for the object behind them to work?

I've got an interface MigrateScenario with its methods. I also have its implementation MigrateScenarioImpl. The instance of MigrateScenarioImpl is being serialized and then passed as a byte[] to some web-service. On the service side, when I try to do this:
Object obj = (new ObjectInputStream(digitalObject.getContent().getInputStream())).readObject();
MigrateScenario mgrScenario = (MigrateScenario) obj;
and what I get is that MigrateScenarioImpl class is missing in the classpath. The obj variable contains that object and the interface should blindly ask for the corresponding methods, since the object "knows itself" how to execute them. However, when I add the MigrateScenarioImpl to the classpath, then all works fine. Am I missing something here?
Would appreciate any help, thanks!
Knowing just the interface doesn't help the JVM know what to do. It needs the Impl to know what to actually do, not just what methods are available.
You can't deserialize a class without having that class known to the classloader (e.g. by being on the classpath). The code for the class itself is not serialized, it is expected to be known on the other end.
When you deserialize the object, Java needs to instantiate and initialize in an instance of the class. Interfaces cannot be instantiated, so Java must instantiate the implementation class. The serialization of a class contains instance data (the values of non transient instance variables), not the code of implemented methods, so there are no methods for the interface to point to.

Categories

Resources