使用POJOS的多态反序列化JSON

时间:2018-10-24 12:20:37

标签: java json spring spring-mvc jackson

我想用jax-rs使用json,我的方法标记看起来像这样。

@PostMapping("/test")
public ResponseEntity<String> consumeJson(@RequestBody TestPojo testPojo)

我的json看起来像

{
  "code": "<code>",
  "display": "<display>",
  "activities": [
    {
      "categoryCode": "drug",                
      "drugDisplay" : "Ceforanide"
    },{
      "categoryCode": "observation",       
      "measurementWeight" : "80kg",                     
    }
  ]

}

我有以下波霍音乐

public class TestPojo implements Serializable{
   private String code;
   private String display;
   private List<ActivityPojo> activities;

   // Getters & Setters
}

现在我有一个超类,并且有几个类从中继承

public class ActivityPojo implements Serializable{
   private String categoryCode;
}

子类

public class DrugPojo extends ActivityPojo implements Serializable{
    private String drugDisplay;
    // Getters & Setters
}


public class ObservationPojo extends ActivityPojo implements Serializable{
    private String measurementWeight;
    // Getters & Setters
}

在我的网络服务方法中,我想做类似的事情

List<ActivityPojo> activities = testPojo.getActivities();
for(int i = 0; i < activities.size(); i++){
    if( activities.get(i) instanceof DrugPojo){
        // do stuff
    }
    else if( activities.get(i) instanceof ObservationPojo){
        // do stuff
    }
}

所以可以多态地序列化我的json来做到这一点。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

这个问题非常棘手,所以我做了一些测试。

如果我正确理解了问题,我认为此类(以及内部的)可以解决问题:

@Component
@SuppressWarnings("serial")
public class ActivityPojoJsonModule extends SimpleModule {

    public ActivityPojoJsonModule() {
        this.addDeserializer(ActivityPojo.class, new ActivityPojoDeserializer());
    }

    public static class ActivityPojoDeserializer extends JsonDeserializer<ActivityPojo> {

        @Override
        public ActivityPojo deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
            ObjectCodec codec = parser.getCodec();
            JsonNode node = codec.readTree(parser);
            if(this.isDrug(node)) {
                return codec.treeToValue(node, DrugPojo.class);
            }
            return codec.treeToValue(node, ObservationPojo.class);
        }

        private boolean isDrug(JsonNode node) {
            return node.get("categoryCode").asText().equals("drug");
        }
    }
}

它向Spring上下文添加了一个组件,该组件将使用基于字段ActivityPojo的值的逻辑对categoryCode进行反序列化。您只需要在扫描的软件包中添加此类,它将覆盖Jackson的默认行为。