Java 使用jackson序列化和反序列化具有抽象字段的对象

Java 使用jackson序列化和反序列化具有抽象字段的对象,java,database,serialization,jackson,deserialization,Java,Database,Serialization,Jackson,Deserialization,我想做的似乎很简单,只需处理如下对象: 当从主体中包含JSON对象的客户端(web浏览器)接收Post请求时,服务器将其反序列化为特定对象,并序列化其某些字段,然后将其保存到数据库中 当从客户机接收Get请求时,服务器从数据库检索对象,对其进行反序列化,将其与其他信息组合,并将其返回给客户机 问题是,对象包含一个抽象字段 保存请求可以很好地工作 当我将这些注释添加到抽象类中时,阶段1可以正常工作 请求JSON: { config: { type: "concreteA", ...}, ...}

我想做的似乎很简单,只需处理如下对象:

  • 当从主体中包含JSON对象的客户端(web浏览器)接收Post请求时,服务器将其反序列化为特定对象,并序列化其某些字段,然后将其保存到数据库中
  • 当从客户机接收Get请求时,服务器从数据库检索对象,对其进行反序列化,将其与其他信息组合,并将其返回给客户机
  • 问题是,对象包含一个抽象字段

    保存请求可以很好地工作 当我将这些注释添加到抽象类中时,阶段1可以正常工作

    请求JSON:

    { config: { type: "concreteA", ...}, ...}
    
    REST API:

    @RequestMapping(value="/configs", method=RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<Object> saveConfig(@RequestBody ConfigRequest request) 
    throws IOException {
    ...
    }
    
    AbstractConfig类,它包含在ConfigRequest中

    @JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
                  include=JsonTypeInfo.As.PROPERTY,
                  property="type",
                  visible=true)
    @JsonSubTypes({@Type(value=ConcreteAConfig.class, name="concreteA")})
    public abstract class AbstractConfig {
        public AbstractConfig(){}
        private String type;
        // Abbr. other fields, and all getters and setters 
    }
    
    反序列化字符串:

    {"type":"concreteA", ...}
    
    反序列化json字符串失败 但当我尝试检索和反序列化(阶段2)时,反序列化失败:

    16/03/24 17:17:20 ERROR (...Abbr...) org.codehaus.jackson.map.JsonMappingException: Can not construct instance of AbstractConfig, problem: abstract types can only be instantiated with additional type information
    
    RowMapper,这会引发错误:

    public class BatchRowMapper implements RowMapper<Batch> {
      private static ObjectMapper objectMapper = new ObjectMapper();
    
      @Override
      public Batch mapRow(ResultSet row, int rowNum) throws SQLException {
        Batch batch = new Batch();
    
        try {
          // THIS METHOD RAISES THE ERROR
          batch.setConfig(objectMapper.readValue(row.getString(CONFIG), AbstractConfig.class));
        } catch (ClassCastException|IOException e) {
          throw new SQLException(e.toString());
        }
    
        return batch;
      }
    }
    
    公共类BatchRowMapper实现了RowMapper{
    私有静态ObjectMapper ObjectMapper=新ObjectMapper();
    @凌驾
    公共批处理mapRow(ResultSet row,int rowNum)引发SQLException{
    批次=新批次();
    试一试{
    //此方法会引发错误
    setConfig(objectMapper.readValue(row.getString(CONFIG),AbstractConfig.class));
    }捕获(ClassCastException | IOException e){
    抛出新的SQLException(例如toString());
    }
    退货批次;
    }
    }
    
    我想使用相同的“类型”字段对抽象字段进行ser/de,并且只使用注释是我的愿望。。。可能吗?如果需要进一步的信息,我愿意。
    提前谢谢。

    我发现问题在于我用了什么


    当我使用codehause的jackson(旧版本)时,JsonTypeInfo的反序列化无法正常工作。fasterxml的Jackson工作得非常完美。

    如果我使用你的代码,它对我来说也很有用<代码>objMapper.readValue(“{\”类型\“:\”具体化\“}”,AbstractConfig.class)public class BatchRowMapper implements RowMapper<Batch> { private static ObjectMapper objectMapper = new ObjectMapper(); @Override public Batch mapRow(ResultSet row, int rowNum) throws SQLException { Batch batch = new Batch(); try { // THIS METHOD RAISES THE ERROR batch.setConfig(objectMapper.readValue(row.getString(CONFIG), AbstractConfig.class)); } catch (ClassCastException|IOException e) { throw new SQLException(e.toString()); } return batch; } }