Search code examples
javajsonjacksonjson-deserializationgenson

deserialize Json to Java with Polymorphic members


I'm trying to deserialize a json string to java object with genson but could not succeed. My class structure is like this:

public class Condition {
}

public class SimpleCondition extends Condition {
    String feature;
    String op;
    String value;
    int primitive;
}

public class ComplexCondition extends Condition {
    private Condition left;
    private String joint;
    private Condition right;
}

As you can see ComplexCondition may have another ComplexCondition or a SimpleCondition as its member for both left and right. The json that I get is like this:

{
  "left": {
            "feature":"locality",
            "op":"==",
            "value":"Chino"
            "primitive":9,
          },
  "joint":"and",
  "right": {
              "feature":"ch4",
              "op":">=",
              "value":"1.5",
              "primitive":3
           }
}

In this json, a ComplexCondition has both left and right as SimpleConditions. But a general json string that I receive could be anything ranging from a SimpleCondition to any level of nesting for ComplexConditions. I tried setting @class values in the json string but still genson could not deserialize it. I appreciate any help in deserializing this json to java using any library.


Solution

  • You can register some aliases for your classes and then refer to them in your json like this:

    Genson genson = new GensonBuilder()
        .addAlias("ComplexCondition", ComplexCondition.class)
        .addAlias("SimpleCondition", SimpleCondition.class)
        .create();
    
    {
      "@class": "ComplexCondition",
      "left": {
                "@class": "SimpleCondition",
                "feature":"locality",
                "op":"==",
                "value":"Chino",
                "primitive":9
              },
      "joint":"and",
      "right": {
                "@class": "SimpleCondition",
                  "feature":"ch4",
                  "op":">=",
                  "value":"1.5",
                  "primitive":3
               }
    }
    

    You also need to add get and set methods for your ComplexCondition or make its field public or provide a constructor which takes them as arguments or configure genson to use private fields.

    And last note, the class metadata attribute must be defined before attributes that are not prefixed by @. If you generate this json with Genson, it will always respect this constraint.