web-dev-qa-db-ja.com

Gsonのデフォルトの引数なしコンストラクタは必須ですか?

Gsonユーザーガイド は、Gsonで適切に動作するように、クラスのデフォルトの引数なしコンストラクターを定義する必要があると述べています。さらに、GsonのInstanceCreatorクラスの javadoc では、デフォルトコンストラクターが欠落しているクラスのインスタンスをデシリアライズしようとすると、例外がスローされると述べ、shouldそのような場合はInstanceCreatorを使用します。ただし、デフォルトのコンストラクターがないクラスでGsonの使用をテストしようとしましたが、シリアル化と逆シリアル化の両方が問題なく動作します。

以下は、逆シリアル化のコードです。引数なしのコンストラクタを持たないクラス:

public class Mushroom {
    private String name;
    private double diameter;

    public Mushroom(String name, double diameter) {
        this.name = name;
        this.diameter = diameter;
    }

    //equals(), hashCode(), etc.
}

およびテスト:

@Test
public void deserializeMushroom() {
    assertEquals(
            new Mushroom("Fly agaric", 4.0),
            new Gson().fromJson(
                    "{name:\"Fly agaric\", diameter:4.0}", Mushroom.class));
}

正常に動作します。

だから私の質問は次のとおりです:実際にデフォルトのコンストラクタを必要とせずにGsonを使用できますか、それが機能しない状況がありますか?

51
raindev

Gson 2.3.1以降。

Gsonのドキュメントの内容に関係なく、クラスに引数なしのコンストラクタがなく、InstanceCreaterオブジェクトを登録していない場合、Reflectionを使用してObjectConstructor(オブジェクトを構築)を作成し、UnsafeAllocatorを作成します。クラスのインスタンスを作成するためのクラスSun.misc.UnsafeallocateInstanceメソッド。

この Unsafe class は、引数のないコンストラクタの欠如を回避し、 他の多くの危険な使用法 を持っています。 allocateInstance状態

インスタンスを割り当てますが、コンストラクターは実行しません。クラスがまだ初期化されていない場合は初期化します。

したがって、実際にはコンストラクターは必要なく、2つの引数コンストラクターを使用します。例を参照してください here

引数なしのコンストラクターがある場合、GsonはObjectConstructorを使用します。これは、デフォルトのConstructorを呼び出して使用します

yourClassType.getDeclaredConstructor(); // ie. empty, no-args

私の2セント:Gsonが言ったことに従い、引数なしのコンストラクタでクラスを作成するか、InstanceCreatorを登録します。 Unsafeを使用すると、自分が悪い位置にいることがあります。

86

ここで説明されているように、 Jackson ライブラリには適切なソリューションがあります。

https://stackoverflow.com/a/11838468/285472

ポイントは、 Mix-Ins feature を介してシリアライザーに伝えることです。引数付きのコンストラクターを使用するときに使用するJSONフィールド。

そのエンティティが外部ライブラリの一部である場合、 Creator feature を使用して「リモート注釈」できます。

1
thomas.mc.work