简体   繁体   中英

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.
  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.

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.

Request JSON:

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

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

@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

But when I try retrieving and deserializing(Phase 2), the deserialization fails:

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:

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? 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 fasterxml works perfectly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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