2017-04-01 7 views
0

私は適切なサブクラスに逆直列化する必要があるオブジェクトのリストを持っています。私は以下のようなgsonオブジェクトを構築することでこれを得ることができました。サブクラスを拡張できるGsonのインスタンスを構築する

JsonDeserializer<Shape> jdTypes = (json, typeOfT, jsonContext) -> { 
     JsonObject jsonObject = json.getAsJsonObject(); 
     int type = jsonObject.get("type").getAsInt(); 

     Gson gson = new Gson(); 

     switch (type){ 
      case Types.TYPE_CARD: 
       return gson.fromJson(json, Card.class); 

      case Types.TYPE_BLOCK: 
       return gson.fromJson(json, Block.class); 

      case Types.TYPE_STRIPE: 
       return gson.fromJson(json, Stripe.class); 

      //... 

     } 
    }; 

    GsonBuilder builder = new GsonBuilder(); 
    builder.registerTypeAdapter(Shape.class, jdTypes); 
    builder.create(); 

これはうまくいく方法です。現在私はGsonBuilder内でGsonのインスタンスを作成しています。 Yikes。異なるサブタイプを非直列化するために構築しようとしているGsonオブジェクトを使用する方法はありますか?

答えて

1

この問題を正しく理解していれば、JsonDeserializationContextを直接使用することができます。

classOfType()は自分の形の typeに対応するクラスを返す必要があり
return jsonContext.deserialize(json, classOfType(type)); 

1

ホイールを改造する必要はありません。あなたの問題はGsonの範囲で古典的であり、正確にそのような種類の問題を解決するように設計された特別なRuntimeTypeAdapterFactoryがあります。

final class Types { 

    private Types() { 
    } 

    static final int TYPE_CARD = 1; 
    static final int TYPE_BLOCK = 2; 
    static final int TYPE_STRIPE = 3; 

    abstract static class Abstract { 

     private Abstract() { } 

     static final class Card extends Abstract { }  
     static final class Block extends Abstract { } 
     static final class Stripe extends Abstract {} 

    } 

} 

あなたはRuntimeTypeAdapterFactoryを設定して使用することができます:あなたはこのようなものがある場合たとえば、

private static final Gson gson = new GsonBuilder() 
     .registerTypeAdapterFactory(
       RuntimeTypeAdapterFactory.of(Types.Abstract.class, "type") 
         .registerSubtype(Types.Abstract.Card.class, String.valueOf(Types.TYPE_CARD)) 
         .registerSubtype(Types.Abstract.Block.class, String.valueOf(Types.TYPE_BLOCK)) 
         .registerSubtype(Types.Abstract.Stripe.class, String.valueOf(Types.TYPE_STRIPE)) 
     ) 
     .create(); 

を次にあなたも何かを必要としない:

private static final Type abstractListType = new TypeToken<List<Types.Abstract>>() { 
}.getType(); 

public static void main(final String... args) { 
    gson.<List<Types.Abstract>>fromJson("[{\"type\":1},{\"type\":2},{\"type\":3}]", abstractListType) 
      .stream() 
      .map(Types.Abstract::getClass) 
      .forEach(System.out::println); 
} 

出力:

クラスq43159721.Types $ Abstract $カード
クラスq43159721.Types $抽象$ブロック
クラスq43159721.Types $抽象$ストライプ

+0

RuntimeTypeAdapterFactoryが定義されたタイプではないでしょうなぜ任意のアイデア? – Canoe

+0

@Canoe 'RuntimeTypeAdapterFactory'はGsonエクストラの一部です。メインライブラリはMaven Centralに公開されていません。コピー/貼り付け、または次のようなものを登録してください:https://mvnrepository.com/artifact/org.danilopianini/gson-extras/0.1.0 –

+0

thanks私は余分なパッケージかもしれないと思っていましたが、Googleによって作成されたものを探していました。これはサードパーティの拡張機能です。ありがとう – Canoe

関連する問題