使用jackson对象标识映射多个文档

时间:2014-01-17 02:22:58

标签: initialization jackson identity

我正在开发一个库,我想将一系列JSON文档转换为对象模型。所有对象都由唯一标识符表示,我想使用Jackson的@JsonIdentityInfo注释来允许生成的对象相互引用。每个对象都有一个id

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="_id")
abstract public class SDBObject extends JSONSerialisable {
  /** The (mongodb) object identifier */
  @JsonProperty("_id")
  private String id;
...
}

然后我想做的就是能够用

链接对象
public class SDBStream extends SDBObject {
  /** The owning node */
  @JsonIdentityReference(alwaysAsId = true)
  @JsonProperty("nid")
  private SDBNode node;
...
}

如果所有内容都作为单个JSON文档出现,那么这很容易。但是,我收到各种对象作为一系列特定类型的文档。

我想要做的是使用现有ID和对象的字典预加载身份映射系统,以便随后解码的文档能够在遇到id时使用现有对象。

我应该将这些信息注入ObjectMapper?

1 个答案:

答案 0 :(得分:1)

似乎最简单的事情是提供DefaultDeserializationContext的子类,该子类扩展findObjectId以绑定已知对象。有点像:

public class SDBDeserializationContext extends DefaultDeserializationContext {
  private SDBContext context;

  public SDBDeserializationContext(DeserializerFactory df,
      DeserializerCache cache, SDBContext context) {
    super(df, cache);
    this.context = context;
  }

  public SDBDeserializationContext(SDBDeserializationContext src,
      DeserializerFactory factory) {
    super(src, factory);
    this.context = src.context;
  }

  public SDBDeserializationContext(SDBDeserializationContext src,
      DeserializationConfig config, JsonParser jp, InjectableValues values) {
    super(src, config, jp, values);
    this.context = src.context;
  }

  @Override
  public DefaultDeserializationContext with(DeserializerFactory factory) {
    return new SDBDeserializationContext(this, factory);
  }

  @Override
  public DefaultDeserializationContext createInstance(
      DeserializationConfig config, JsonParser jp, InjectableValues values) {
    return new SDBDeserializationContext(this, config, jp, values);
  }

  @Override
  public ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator) {
    ReadableObjectId oid = super.findObjectId(id, generator);

    if (oid.item == null && this.context != null) {
      SDBObject object = this.context.findBinding(id);
      if (object != null)
        try {
          oid.bindItem(object);
        } catch (IOException ex) {
          throw new IllegalStateException("Unable to bind " + object + " to " + id, ex);
        }
    }
    return oid; 
  }
}