Alexandre LEBRUN Alexandre LEBRUN - 3 months ago 20
JSON Question

Type choice for Play Framework JSON Form

I am developing a REST webservice using the Play Framework 2.5 (Java) and the form data binding (from Spring Framework).
I am quite experienced with this API and like the way it formalizes validation constraints (e.g. Required), so I would like to avoid using the BodyParser API.

I need to parse a JSON request such as this :

{
"elements": [
{
"val": "1"
},
{
"val": ["1","2","3"]
}
]
}


The problem is that "val" accepts two different types : a string (java.lang.String in Java) and an array of strings (java.util.List in my code).

How could I "typesafely" model such a JSON form in my Java code ?
I have already tried to use an abstract (and generic) class implemented by two different subclasses with different types for the "val" attribute, but Spring fails to instantiate the object (BeanInstantiationException).

Here is the current data model :

public class Foo {

@Constraints.Required
public List<Fii> elements;

}

public class Fii {

@Constraints.Required
// Which type ? Object ?
public ? val;

}

Answer
public class Response
{
    List<ResponseEntry> response;
    /*getters + setters */

    public static class ResponseEntry
    {
         private List<Value> elements;
         /*setters + getters*/

         public static class Value
         {
             private List<Object> val;
         }
    }
}

Unfortunately, with the structure of the JSON you are handling, the only way to deserialize it is to have the value attribute be type Object. However, once the JSON is deserialized, you can easily figure out whether value is an object or a single value.

Notice that JSON only supports five data types: objects (Map in java), arrays, strings, numeric and boolean. It looks like in your case, value would most likely be either a number or a map of numbers; then you have two possibilities to check for. Using a quick instanceof comparison, you should be able to figure out what type of value it is.

ObjectMapper mapper = new ObjectMapper();
Response r = mapper.readValues(json, Response.class);
Value val = r.response.get(0).values.get(0);
if (val.value instanceof Map)
    ; // multiple
else
    ; // single