I have JSON like the following:
[{
'kind':'1',
'value1': 'foo',
'value2': 'bar',
...
},
{
'kind':'2',
'value1': 'foo',
'value2': 'bar',
...
}
..]
Basically a list of objects with the same variables. In my code, I'd like to create an ArrayList of some class A, which would contain these objects. However, I'd like each object to be of subclass One or Two, depending on the 'kind' value.
How can I accomplish this?
Thanks!
This is what Jackson calls "polymorphic type handling". There's a good explanation of how to do this here. You need to tell Jackson to put the class name into the JSON when you serialize it, and use that class name when you deserialize it. This is done via annotation:
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY, property="kind")
[Source: #StaxMan (below).]
If you don't have control over the JSON format, you can use Jackson to deserialize it into some common intermediate object and then write code that creates the desired subclass object from it. Alternatively, use the json.org library to deserialize the JSON string into an org.json.JSONObject, and then write code to construct your desired objects based on the JSONObject's properties.
Related
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.
I've a class CONTAINER, that contains a List .
BaseClass is not an abstract class, but there is 2 subtypes of BaseClass : BaseClassA and BaseClassB which each have extra fields.
BaseClass has an attribut enum Type, from which i can determinate if an object is BaseClass, BaseClassA or BaseClassB and that i want to use as a discriminator.
How can i tell Jackson the discriminator so when it deserialize the json string, it builds the correct object. At the moment every object is instancied as a BaseClass so i cannot cast it in my java code.
The same way as #DiscriminatorFormula & #DiscriminatorValue work for hibernate and entities
I've found this question : How can I polymorphic deserialization Json String using Java and Jackson Library? which is kinda close but here the user only wants the basic type.
Guessing you have probably solved this but if not check out JsonTypeInfo as a way to annotate classes with subtypes for desrialization. This link http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html has a good explanation that is still valid. If you can't annotate your classes you can use configuration to set up mix-ins (see https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations) that allow you to add annotations to existing classes.
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.
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.
I'm using Jackson to deserialize some JSON into Java POJOs. I register the MrBean module with my object mapper, so all I have to do is define a bunch of interfaces, and the POJOs are generated automagically, based on those interfaces.
I would like to have a Credentials interface with various types of credentials that extend it, e.g. UsernamePasswordCredentials and CertificateFileCredentials.
Doing this without any annotations or other incantations to try to make it work gives me the following error in my unit test:
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "username" (Class org.codehaus.jackson.generated.SCRUBBED.Credentials), not marked as ignorable
at [Source: java.io.StringReader#e0b6f5; line: 32, column: 29] (through reference chain: HostConfiguration["hostDefinitions"]->HostDefinition["credentials"]->Credentials["username"])
I've also followed the instructions at another StackOverflow post, and I'm getting the same error.
The error makes sense; Jackson is trying to map the contents of my JSON file to an empty interface. However, I (naively, perhaps) expected Jackson to look for interfaces that extend the base Credentials interface and try to match up the fields in those interfaces to the fields it found in the JSON object.
I've seen some examples at the Jackson wiki that make use of meta-information in the JSON object, e.g. decorating an object with "#class":"foo.bar.CertificateFileCredentials", but I'd prefer to avoid any of that since my JSON input will be generated automatically by other services, and those other services shouldn't have to know anything about the internals of my service.
Thanks!
How would you define actual implementation classes? As additional interfaces? Those should get generated correctly; but the problem is during deserialization: there must be some way for deserializer to find out actual type to use, if there are multiple choices.
For this, #JsonTypeInfo is recommended to be used as you have noticed.
Actually, the technique would work well for your purposes too, even though you don't control the service that generates the JSON.
Saving the class name is a nice easy default when using #JsonTypeInfo but Jackson lets you customize this to your liking.
For example, suppose the service generates JSON that looks like this:
{ meows: 400, furColor: "green", species: "cat" }
Then you can define these interfaces to convert it properly.
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY,property="species")
#JsonSubTypes({
#JsonSubTypes.Type(value=Feline.class, name="cat")
})
public interface Animal {
public String getFurColor();
}
#JsonTypeName("cat")
public interface Feline extends Animal {
#JsonProperty("meows") // just to have an example of a renamed property...
public long getMeowingVolumeInDecibels();
}
Then you should just automatically get the right java type at runtime when deserializing, as well as automatically generate the "species" property depending on the runtime type. Hope that helps!