<img height="1" width="1" style="display:none;" alt="" src="https://px.ads.linkedin.com/collect/?pid=299788&amp;fmt=gif">

Flexjson Deserialization Example Sample

Software Development, Java

By Ryan Peterson

Recently I came across a situation where I needed to be able to deserialize a decently complex custom domain object from JSON back into Java. The entity contained several collections of custom objects, and in some cases collections of interfaces to more custom implementations of domain objects. This is a quick cheat-sheet guide on how to convert the JSON back into Java objects using Flexjson version 3.2.


On its own, Flexjson is already very good at re-hydrating Java objects. In my case, the class info was excluded from the JSON being submitted for de-serialization, so a bit more work has to be done.

A quick example of the method I'm using is:


public static MyDomainObject fromJson(String myDomainObjectJson) {
    return new JSONDeserializer<MyDomainObject>()
        .use(null, MyDomainObject.class)
        .use("canEdit", new EditEmployeeTreeSetJsonFactory())
        .use("data", ArrayList.class)
        .use("data.values", new TypeLocator<String>("myValueType")
            .add("numerical", NumericalObjectData.class)
            .add("date", DateObjectData.class)
            .add("string", StringObjectData.class)
        ).deserialize(myDomainObjectJson);
}


Returning a new JSONDeserializer typed as my object is a standard Flexjson thing. This should populate all the parameters for the root object with the corresponding JSON values. The .use allows more custom handling of the fields:
Custom ObjectFactories can be defined which implement the Flexjson ObjectFactory. More info can be found in the Flexjson documentation.

The main caveat I found was how the definition of the custom ObjectFactory is handled. If there's a list of values as a parameter on your object, say:


List<Employee> employees = new ArrayList();
If you specify:  .use ("employees", new EmployeeArrayListJsonFactory()), the entire list of JSON values (a list of maps) will be presented to the factory. On the other hand, if you specify: .use("employees", ArrayList.class), .use("employees.values", new EmployeeArrayListJsonFactory()), each individual employee entry within the list will instead be presented to the factory (a single Map representing each individual entry).


The last caveat I found using the custom ObjectFactory is the return type of collection in the first example must exactly match the defined type as the parameter.  In other words:  In my example, the List of employees is an ArrayList.  In the first usage of the factory, it would have to return an ArrayList of employee objects.


A quick example  that returns a TreeSet of Employees for the original MyDomainObject would be:


@Overrid
public TreeSet<Employee> instantiate(ObjectBinder context, Object value, Type targetType, Class targetClass) {
    if (value instanceof List) {
        List<String> employeeIds = new ArrayList<String>();
        for (Map<String, String> employeeJsonMap : (List<Map<String, String>>)value) {
            employeeIds.add(employeeJsonMap.get("id"));
        }
        return new TreeSet<Employee>(employeeRepositoryService.findEmployeesById(employeeIds));
    } else {
    
        return null;  // Some kind of error happened
    
    }
}


This method obtains the employeeId from each element in the given JSON, and does a repository lookup to add that employee to the resulting TreeSet.  I wound up implementing two versions for each domain object: This one that retrieves existing entities, and one that creates new detached entities built using only the information given in the JSON.


Hopefully this information and examples can help out if you find yourself in a similar situation, needing to deserialize a complex object model.

Managing JIRA at Scale White Paper

TAGS: Software Development, Java

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Subscribe to Our Newsletter

Recent Blog Posts