提前致歉。这似乎是一项简单的任务,但数小时后在Google上进行了猜测/检查,但我仍然无法弄清楚。

我正在为公司提供的API编写Java便捷包装器库。其中一个类如下所示:

class View extends Model<View>
{
    List<Column> columns;
    Column primaryColumn;
}


但是,我们的API实际上需要一个primaryColumnId整数,而不是实际的Column对象。我想在库中维护强类型的getPrimaryColumn()setPrimaryColumn(Column)以减少开发人员错误,但是我很难在我们需要从/从/从到的getter / setter之间编写某种转换。 JSON。

我正在使用标准Bean序列化策略。我想避免使用完全自定义的方法,因为实际上View有很多字段。到目前为止,这是我所发现的。

我认为(尚未测试)我可以通过创建一个类似于以下内容的自定义JsonSerializer来处理序列化情况:

public static class ColumnIdSerializer extends JsonSerializer<Column>
    {
        @Override
        public void serialize(Column column, JsonGenerator jsonGenerator,
                              SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeFieldName("primaryColumnId");
            jsonGenerator.writeNumber(column.id);
        }
    }


然后将注释分配到适当的位置:

@JsonSerialize(using = Column.ColumnIdSerializer.class)
public Column getPrimaryColumn() { /* ... */ }


这使我可以序列化id而不是整个类,并将键从primaryColumn重命名为primaryColumnId

现在,我们开始进行反序列化。在这里,我遇到三个问题。

首先是为了成功从ID反序列化列,我们必须首先具有列列表。使用类上的@JsonPropertyOrder可以解决此问题。太好了!

第二个是我需要告诉Jackson在primaryColumnId下而不是primaryColumn下查找值。我不知道该怎么做; JsonDeserializer似乎在找到密钥后即刻启动,因此修改它为时已晚。 JsonSchema看起来可能很相关,但是我找不到任何文档或有关如何使用它的互联网信息。

第三个是,在自定义JsonDeserializer类中,我将必须能够引用要反序列化的View,以便为它提供一个Column来代替我的id int。似乎没有办法做到这一点。

我应该只是添加一个公共的getPrimaryColumnId()setPrimaryColumnId(Integer),还是有办法克服这些障碍?

最佳答案

所以我建议这样的事情:

class CustomView
{
    private final View parent;
    public CustomView(View view){
        parent = view;
    }

    // Jackson needs a no-arg constructor
    public CustomView(){
        parent = new View();
    }

    // ...
    public List<Columns> getColumns(){ ... }
    public void setColumns(List<Columns> columns){ ... }

    public int getPrimaryColumn(){
        return parent.getPrimaryColumn().getColumnId();
    }
    public void setPrimaryColumn(int column){
        parent.getPrimaryColumn().setColumnId(column);
    }
    //...

    // don't use `get` in the method name here to avoid serialization
    public View rawView(){
        return parent;
    }
}


如果需要,可以编写扩展View的方法,但是要注意在适当的地方屏蔽方法。

10-08 15:34