簡體   English   中英

使用自定義typeadapter,json中的jsonwriter添加對象

[英]adding an object using a custom typeadapter, jsonwriter in gson

gson是一個很棒的圖書館 - 它運作良好。 有時我有自定義要求,可以制作和注冊TypeAdapters和TypeAdaptorFactories - 這也很有效。

然而令我困惑的是,如何委托回json序列化...大多數時候我需要這個用於集合,但為了說明這一點 - 假設我有一個對類,gson顯然會愉快地序列化,但由於某種原因我需要自己的自定義序列化程序。 好吧......如果我的配對是

public class Pair
{
    public final Object First;
    public final Object Second; 
    public Pair( Object first, Object second) {this.first = first; this.second = second};
}

如果我為此編寫了一個類型適配器 - 您希望 write函數看起來像:

public void write( JsonWriter out, Pair pair )
{
    out.beginObject();
    out.name( "first");
    out.value( pair.first );         // can't do this
    out.name( "second");
    out.value( pair.second);         // or this
    out.endObject();
}

所以你可以看到問題 - 我不知道第一個和第二個的類型,也不知道它們是如何序列化的。 我可以使用gson.toJson來序列化第一個和第二個 - 但是如果我將它們作為字符串添加到編寫器中,它們將被轉義。 有一個gson.tojson函數,它接受一個值和一個編寫器 - 但它也需要一個typetoken - 我沒有。 我得到的印象是,我打算從某個地方安裝另一個類型的適配器 - 但是當我只有一個對象列表時......我從哪里得到它? 我只是獲得對象的適配器?

我有點困惑? 當然這是最常見的用例? 大多數自定義序列化程序將用於T或T樹之類的奇怪列表,並且你真的不知道列表中的內容,除了它繼承自T ...所以你需要能夠委托回來序列化在某種程度上?

無論如何 - 如果有人能告訴我如何編寫上述功能,我真的很感激!

在這種情況下,最好使用JsonSerializer而不是TypeAdapter ,原因很簡單,序列化程序可以訪問它們的序列化上下文:

public class PairSerializer implements JsonSerializer<Pair> {

    public PairSerializer() {
        super();
    }

    @Override
    public JsonElement serialize(final Pair value, final Type type,
            final JsonSerializationContext context) {
        final JsonObject jsonObj = new JsonObject();
        jsonObj.add("first", context.serialize(value.getFirst()));
        jsonObj.add("second", context.serialize(value.getSecond()));

        return jsonObj;
    }
}

上面的示例代碼說明了如何將目標對象的序列化委托回主marshaller。 這個的主要優點(除了避免復雜的解決方法)是您仍然可以利用可能已在主上下文中注冊的其他類型適配器和自定義序列化程序。 請注意,序列化程序和適配器的注冊使用完全相同的代碼:

// With adapter
final Gson gson = new GsonBuilder().registerTypeAdapter(Pair.class,
        new PairAdapter()).create();

// With serializer
final Gson gson = new GsonBuilder().registerTypeAdapter(Pair.class,
        new PairSerializer()).create();

如果您發現需要使用適配器,那么您可以使用嵌入式Gson代理為您序列化Pair屬性,但缺點是您無法訪問在父Gson代理上進行的自定義注冊:

public class PairAdapter extends TypeAdapter<Pair> {
    final Gson embedded = new Gson();

    public PairAdapter() {
        super();
    }

    @Override
    public void write(final JsonWriter out, final Pair value)
            throws IOException {
        out.beginObject();

        out.name("first");
        embedded.toJson(embedded.toJsonTree(value.getFirst()), out);

        out.name("second");
        embedded.toJson(embedded.toJsonTree(value.getSecond()), out);

        out.endObject();
    }

    @Override
    public Pair read(JsonReader in) throws IOException {
        throw new UnsupportedOperationException();
    }
}

實際上似乎工作 - 獲取對象的適配器 - 使用typeadaptorfactory發現對象上的“json”方法,並讓該存儲遠離適配器對象。 對於這樣一個明顯的用例來說,似乎非常復雜嗎?

例如:

public static @Nullable
TypeAdapter<ImmutableStack<?>> json(final Gson gson)
{
    final TypeAdapter<Object> adaptor = gson.getAdapter(Object.class);
    return new TypeAdapter<ImmutableStack<?>>()
    {
        @Override
        public ImmutableStack<?> read(@Nullable final JsonReader in) throws IOException
        {
            throw ProgramError.notImplementedYet();
        }
        @Override
        public void write(final JsonWriter out, final ImmutableStack<?> value) throws IOException
        {
            out.beginArray();
            for (final Object inner : value)
                adaptor.write(out, inner);
            out.endArray();
        }
    };
}

有誰知道更好的方法嗎?

暫無
暫無

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

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