Jackson deserializing nested polymorphic type

后端 未结 2 594
遥遥无期
遥遥无期 2020-12-19 22:20

I\'m trying to use Jakson to deserialize a nested polymorphic type. Meaning my top level type referes to another polymorphic type that finally is extended by class that\'s n

相关标签:
2条回答
  • 2020-12-19 22:39

    First of all the class name in your json is wrong it should be com.adfin.JasksonDouble$FinalLevel, dollar instead of dot.

    Here is a code that works, but I am not sure if it answers right to all the subtypes stuff.

    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
    public static abstract class FirstLevel {
        public abstract String getTestValue();
    }
    

    Remove the annotations from the other classes and it should work (just tested it).

    However all this stuff looks quite complex, if you are free to try another library you might want to have a look at Genson. To enable polymorphic types support you have to configure your Genson instance. If you are also the one producing the json you don't need anything else (as you could use Genson to produce the json stream as needed to handle polymorphic types).

    Here is an example:

    // enable polymorphic types support
    Genson genson = new Genson.Builder().setWithClassMetadata(true).create();
    // the @class must be first property in the json object
    String testStr = "{ \"@class\": \"com.adfin.JasksonDouble$FinalLevel\", \"test\": \"foo\"}";
    FirstLevel result = genson.deserialize(testStr, FirstLevel.class);
    System.out.println(result.getTestValue());
    

    Another nice thing with Genson is that it gives you the ability to register aliases for your classes, so you do not have to make all the package info available in your stream. THe other advantage is that if you store a json stream in a data base and move your class into another package, you only have to change the alias in your app and not to migrate all the json streams from the DB.

    Genson genson = new Genson.Builder().setWithClassMetadata(true)
                                        .addAlias("FinalLevel", FinalLevel.class)
                                        .create();
    // the @class must be first property in the json object
    String testStr = "{ \"@class\": \"FinalLevel\", \"test\": \"foo\"}";
    FirstLevel result = genson.deserialize(testStr, FirstLevel.class);
    System.out.println(result.getTestValue());
    
    0 讨论(0)
  • 2020-12-19 22:45

    Your definitions are messed up -- you are trying to use two type identifiers, type name AND class. This does not make any sense. You should choose one method or the other, not both.

    If you choose Java class name as type information, just leave out the name. Also, you only need to include @JsonTypeInfo for FirstLevel; sub-classes inherit this definition.

    If you prefer use of logical type name, drop the class property. You will also need to specify sub-type list, either with annotation, or by registering them via ObjectMapper.

    0 讨论(0)
提交回复
热议问题