簡體   English   中英

傑克遜(Jackson)Ser / Deser:將對象代理到帶有不同密鑰的ID /從ID代理

[英]Jackson Ser/Deser: Proxying an object to/from an id w/ a different key

提前致歉。 這似乎是一項簡單的任務,但數小時后在Google上進行了猜測/檢查,但我仍然無法弄清楚。

我正在為公司提供的API編寫Java便捷包裝器庫。 其中一個類如下所示:

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

但是,我們的API實際上需要的是primaryColumnId整數,而不是實際的Column對象。 我想在庫中維護強類型化的getPrimaryColumn()setPrimaryColumn(Column)以減少開發人員錯誤,但是我在編寫需要對/進行ser / deser的getter / setter之間的某種轉換時遇到了很大的困難從JSON。

我正在使用標准Bean序列化策略。 我想避免使用完全自定義的方法,因為實際上View有很多領域。 到目前為止,這是我想出的。

認為 (尚未測試)我可以通過創建一個自定義JsonSerializer來處理序列化情況,該自定義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 ,但是要注意在適當的地方屏蔽方法。

事實證明,由於傑克遜進行了令人討厭的反思,因此可以通過private方法進行查看。 因此,把戲最終只是按照以下思路進行:

private void setPrimaryColumnId(Integer id) {...}

private Integer getPrimaryColumnId() {...}

public void setPrimaryColumn(Column column) {...}

@JsonIgnore
public Column getPrimaryColumn() {...}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM