flexjson
Class JSONDeserializer<T>

java.lang.Object
  extended by flexjson.JSONDeserializer<T>

public class JSONDeserializer<T>
extends Object

JSONDeserializer takes as input a json string and produces a static typed object graph from that json representation. By default it uses the class property in the json data in order to map the untyped generic json data into a specific Java type. However, you are limited to only json strings with class information embedded when resolving it into a Java type. But, for now let's just look at the simplest case of class attributes in your json. We'll look at how JSONSerializer and JSONDeserializer pair together out of the box.

Say we have a simple object like Hero (see the superhero package under the test and mock). To create a json represenation of Hero we'd do the following:

   Hero harveyBirdman = new Hero("Harvey Birdman", new SecretIdentity("Attorney At Law"), new SecretLair("Sebben & Sebben") );
   String jsonHarvey = new JSONSerialize().serialize(hero);
 

Now to reconsitute Harvey to fight for the law we'd use JSONDeserializer like so:

   Hero hero = new JSONDeserializer().deserialize( jsonHarvey );
 

Pretty easy when all the type information is included with the JSON data. Now let's look at the more difficult case of how we might reconstitute something missing type info.

Let's exclude the class attribute in our json like so:

   String jsonHarvey = new JSONSerialize().exclude("*.class").serialize(hero);
 

The big trick here is to replace that type information when we instantiate the deserializer. To do that we'll use the use(String, Class) method like so:

   Hero hero = new JSONDeserializer().use( null, Hero.class ).deserialize( jsonHarvey );
 

Like riding a horse with no saddle without our type information. So what is happening here is we've registered the Hero class to the root of the json. The use(String, Class) method uses the object graph path to attach certain classes to those locations. So, when the deserializer is deserializing it knows where it is in the object graph. It uses that graph path to look up the java class it should use when reconstituting the object.

Notice that in our json you'd see there is no type information in the stream. However, all we had to do is point the class at the Hero object, and it figured it out. That's because it uses the target type (in this case Hero) to figure out the other types by inspecting that class. Meaning notice that we didn't have to tell it about SecretLair or SecretIdentity. That's because it can figure that out from the Hero class.

Pretty cool. Where this fails is when we starting working with interfaces, abstract classes, and subclasses. Yea our friend polymorphism can be a pain when deserializing. Why? Well if you haven't realized by now inspecting the type from our target class won't help us because either it's not a concrete class or we can't tell the subclass by looking at the super class alone. Next section we're going to stand up on our bare back horse. Ready? Let's do it.

Before we showed how the use(String, Class) method would allow us to plug in a single class for a given path. That might work when you know exactly which class you want to instantiate, but when the class type depends on external factors we really need a way to specify several possibilities. That's where the second version of use(String, ClassLocator) comes into play. ClassLocator allow you to use a stradegy for finding which java Class you want to attach at a particular object path.

use(String, ClassLocator) have access to the intermediate form of the object as a Map. Given the Map at the object path the ClassLocator figures out which Class Flexjson will bind the parameters into that object.

Let's take a look at how this can be done using our Hero class. All Heros have a list of super powers. These super powers are things like X Ray Vision, Heat Vision, Flight, etc. Each super power is represented by a subclass of SuperPower. If we serialize a Hero without class information embedded we'll need a way to figure out which instance to instantiate when we deserialize. In this example I'm going to use a Transformer during serialization to embed a special type information into the object. All this transformer does is strip off the package information on the class property.

 String json = new JSONSerializer()
      .include("powers.class")
      .transform( new SimpleTransformer(), "powers.class")
      .exclude("*.class")
      .serialize( superhero );
 Hero hero = new JSONDeserializer()
      .use("powers.class", new PackageClassLocator())
      .deserialize( json );
 

All objects that pass through the deserializer must have a no argument constructor. The no argument constructor does not have to be public. That allows you to maintain some encapsulation. JSONDeserializer will bind parameters using setter methods of the objects instantiated if available. If a setter method is not available it will using reflection to set the value directly into the field. You can use setter methods transform the any data from json into the object structure you want. That way json structure can be different from your Java object structure. The works very much in the same way getters do for the JSONSerializer.

Collections and Maps have changed the path structure in order to specify concrete classes for both the Collection implementation and the contained values. Normally you would use generics to specify the concrete class to load. However, if you're contained class is an interface or abstract class then you'll need to define those concrete classes using paths. To specify the concrete class for a Collection use the path to the collection. To specify the contained instance's concrete class append "values" onto the path. For example, if your collection path is "person.friends" you can specify the collection type using:

 new JSONDeserializer().use("person.friends", ArrayList.class).use("person.friends.values", Frienemies.class)
 

Notice that append "values" onto the "person.friends" to specify the class to use inside the Collection. Maps have both keys and values within them. For Maps you can specify those by appending "keys" and "values" to the path.

Now onto the advanced topics of the deserializer. ObjectFactory interface is the underpinnings of the deserializer. All object creation is controlled by ObjectFactories. By default there are many ObjectFactories registered to handle all of the default types supported. However, you can add your own implementations to handle specialized formats. For example, say you've encoded your Dates using yyyy.MM.dd. If you want to read these into java.util.Date objects you can register a DateTransformer to deserialize dates into Date objects.


Constructor Summary
JSONDeserializer()
           
 
Method Summary
 T deserialize(Reader input)
          Same as deserialize(String), but uses an instance of java.io.Reader as json input.
 T deserialize(Reader input, Class root)
          Same as deserialize(String, Class), but uses an instance of java.io.Reader as json input.
 T deserialize(Reader input, ObjectFactory factory)
          Same as deserialize(String, ObjectFactory), but uses an instance of java.io.Reader as json input.
 T deserialize(Reader input, String path, Class root)
          Same as deserialize(java.io.Reader, Class) but it starts binding into the instance of the given Class at the given path.
 T deserialize(Reader input, String path, ObjectFactory factory)
          Same as deserialize(String, ObjectFactory), it starts binding into the instance of the given Class at the given path.
 T deserialize(String input)
          Deserialize the given json formatted input into a Java object.
 T deserialize(String input, Class root)
          Deserialize the given json input, and use the given Class as the type of the initial object to deserialize into.
 T deserialize(String input, ObjectFactory factory)
          Deserialize the given json input, and use the given ObjectFactory to create the initial object to deserialize into.
 T deserialize(String input, String path, Class root)
          Same as deserialize(String, Class) but it starts binding into the instance of the given Class at the given path.
 T deserialize(String input, String path, ObjectFactory factory)
          Same as deserialize(String, ObjectFactory), it starts binding into the instance of the given Class at the given path.
 T deserializeInto(Reader input, String path, T target)
          Same as deserializeInto(String, String, Object), but uses an instance of java.io.Reader as json input.
 T deserializeInto(Reader input, T target)
          Same as deserializeInto(String, Object), but uses an instance of java.io.Reader as json input.
 T deserializeInto(String input, String path, T target)
          Deserialize the given input into the existing object target.
 T deserializeInto(String input, T target)
          Deserialize the given input into the existing object target.
 JSONDeserializer<T> use(Class clazz, ObjectFactory factory)
           
 JSONDeserializer<T> use(ObjectFactory factory, String... paths)
           
 JSONDeserializer<T> use(String path, Class clazz)
           
 JSONDeserializer<T> use(String path, ClassLocator locator)
           
 JSONDeserializer<T> use(String path, ObjectFactory factory)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

JSONDeserializer

public JSONDeserializer()
Method Detail

deserialize

public T deserialize(String input)
Deserialize the given json formatted input into a Java object.

Parameters:
input - a json formatted string.
Returns:
an Java instance deserialized from the json input.

deserialize

public T deserialize(Reader input)
Same as deserialize(String), but uses an instance of java.io.Reader as json input.

Parameters:
input - the stream where the json input is coming from.
Returns:
an Java instance deserialized from the java.io.Reader's input.

deserialize

public T deserialize(String input,
                     Class root)
Deserialize the given json input, and use the given Class as the type of the initial object to deserialize into. This object must implement a no-arg constructor.

Parameters:
input - a json formatted string.
root - a Class used to create the initial object.
Returns:
the object created from the given json input.

deserialize

public T deserialize(Reader input,
                     Class root)
Same as deserialize(String, Class), but uses an instance of java.io.Reader as json input.

Parameters:
input - the stream where the json input is coming from.
root - a Class used to create the initial object.
Returns:
an Java instance deserialized from the java.io.Reader's input.

deserialize

public T deserialize(String input,
                     String path,
                     Class root)
Same as deserialize(String, Class) but it starts binding into the instance of the given Class at the given path.

Parameters:
input - a json format string.
path - a path to an instance of the given class.
root - the Class used to create the initial object. Must have a no-arg constructor.
Returns:
the object created from the given json input.

deserialize

public T deserialize(Reader input,
                     String path,
                     Class root)
Same as deserialize(java.io.Reader, Class) but it starts binding into the instance of the given Class at the given path.

Parameters:
input - the stream where the json input is coming from.
path - a path to an instance of the given class.
root - the Class used to create the initial object. Must have a no-arg constructor.
Returns:
an Java instance deserialized from the java.io.Reader's input.

deserialize

public T deserialize(String input,
                     ObjectFactory factory)
Deserialize the given json input, and use the given ObjectFactory to create the initial object to deserialize into.

Parameters:
input - a json formatted string.
factory - an ObjectFactory used to create the initial object.
Returns:
the object created from the given json input.

deserialize

public T deserialize(Reader input,
                     ObjectFactory factory)
Same as deserialize(String, ObjectFactory), but uses an instance of java.io.Reader as json input.

Parameters:
input - the stream where the json input is coming from.
factory - an ObjectFactory used to create the initial object.
Returns:
an Java instance deserialized from the java.io.Reader's input.

deserialize

public T deserialize(String input,
                     String path,
                     ObjectFactory factory)
Same as deserialize(String, ObjectFactory), it starts binding into the instance of the given Class at the given path.

Parameters:
input - a json formatted string.
path - the path two which you start binding.
factory - an ObjectFactory used to create the initial object.
Returns:
an Java instance deserialized from the given json input.

deserialize

public T deserialize(Reader input,
                     String path,
                     ObjectFactory factory)
Same as deserialize(String, ObjectFactory), it starts binding into the instance of the given Class at the given path.

Parameters:
input - the stream where the json input is coming from.
path - the path two which you start binding.
factory - an ObjectFactory used to create the initial object.
Returns:
an Java instance deserialized from the java.io.Reader's input.

deserializeInto

public T deserializeInto(String input,
                         T target)
Deserialize the given input into the existing object target. Values in the json input will overwrite values in the target object. This means if a value is included in json a new object will be created and set into the existing object.

Parameters:
input - a json formatted string.
target - an instance to set values into from the json string.
Returns:
will return a reference to target.

deserializeInto

public T deserializeInto(Reader input,
                         T target)
Same as deserializeInto(String, Object), but uses an instance of java.io.Reader as json input.

Parameters:
input - the stream where the json input is coming from.
target - an instance to set values into from the json string.
Returns:
will return a reference to target.

deserializeInto

public T deserializeInto(String input,
                         String path,
                         T target)
Deserialize the given input into the existing object target. Values in the json input will overwrite values in the target object. This means if a value is included in json a new object will be created and set into the existing object.

Parameters:
input - a json formatted string.
path - the path two which you start binding.
target - an instance to set values into from the json string.
Returns:
will return a reference to target.

deserializeInto

public T deserializeInto(Reader input,
                         String path,
                         T target)
Same as deserializeInto(String, String, Object), but uses an instance of java.io.Reader as json input.

Parameters:
input - the stream where the json input is coming from.
path - the path two which you start binding.
target - an instance to set values into from the json string.
Returns:
will return a reference to target.

use

public JSONDeserializer<T> use(String path,
                               ClassLocator locator)

use

public JSONDeserializer<T> use(String path,
                               Class clazz)

use

public JSONDeserializer<T> use(Class clazz,
                               ObjectFactory factory)

use

public JSONDeserializer<T> use(String path,
                               ObjectFactory factory)

use

public JSONDeserializer<T> use(ObjectFactory factory,
                               String... paths)


Copyright © 2014. All Rights Reserved.