简体   繁体   English

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

[英]Serialize and deserialize an object with an abstract field using jackson

What I'd like to do seems simple, just handling an object like the following:我想做的事情看起来很简单,只需处理如下所示的对象:

  1. When receiving a Post request from a client(web browser), which has a JSON object in its body, the server deserializes it into a certain object, and serializes some of its fields then saves them into a database.当收到来自客户端(Web 浏览器)的 Post 请求时,它的主体中有一个 JSON 对象,服务器将其反序列化为某个对象,并序列化其某些字段,然后将它们保存到数据库中。
  2. When receiving a Get request from the client, the server retrieves the object from the database, deserializes it, composes it with other information and gives it back to the client.当收到来自客户端的 Get 请求时,服务器从数据库中检索对象,对其进行反序列化,将其与其他信息组合并将其返回给客户端。

The problem is, the object contains an abstract field.问题是,对象包含一个抽象字段。

Saving a request works fine保存请求工作正常

When I add these annotations to the abstract class, the phase 1 works fine.当我将这些注释添加到抽象类时,阶段 1 工作正常。

Request JSON:请求 JSON:

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

REST API: REST API:

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

ConfigRequest class:配置请求类:

public class ConfigRequest {
    private AbstractConfig config;
    // Abbr. other fields, and all getters and setters 
}

AbstractConfig class, which is included in ConfigRequest 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 
}

Deserialized string:反序列化字符串:

{"type":"concreteA", ...}

Deserializing the json string fails反序列化 json 字符串失败

But when I try retrieving and deserializing(Phase 2), the deserialization fails:但是当我尝试检索和反序列化(第 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, which raises the error: 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;
  }
}

I'd like to ser/de an abstract field with the same "type" field, and using only annotaions is my wish... Is it possible?我想使用相同的“类型”字段来 ser/de 抽象字段,并且只使用 annotaions 是我的愿望......这可能吗? If further information needed, I will be willing.如果需要进一步的信息,我愿意。 Thank you in advance.先感谢您。

I've found it's the problem what Jackson I used.我发现这是我使用的杰克逊的问题。

When I use jackson of codehause(older), deserialization with JsonTypeInfo doesn't work properly.当我使用 jackson of codehause(旧)时,使用 JsonTypeInfo 进行反序列化无法正常工作。 Jackson of fasterxml works perfectly. fastxml 的 Jackson 工作得很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM