2017-07-13 11 views
2

gsonを使用して、多くの異なるクラスのインスタンスを含むjsonを逆シリアル化しています。次の作品は限り私はアップフロントのすべてのクラスを知っているとして、次のようJavaのクラス名から型を取得する方法

String receivedPayloadStr = receivedMessage.get("payload"); 
    Type payloadType = getType(receivedMessage.get("type").toString()); 
    Object typedPayload = gson.fromJson(payloadJson, payloadType); 
    System.out.println(typedPayload); 

私のgetType機能は次のとおりです。

、短期的に動作しますが、醜いと壊れやすい
static Type getType(String typeName){ 
    switch (typeName){ 
     case "mypackage1.MyThing1": 
      return new TypeToken<MyThing1>() {}.getType(); 
     case "mypackage2.MyThing1": 
      return new TypeToken<MyThing2>() {}.getType(); 
     default: 
      throw new RuntimeException("Unsupported type: " + typeName); 
    } 
} 

。明らかに、私たちはより保守的なアプローチを望んでいます。一般的な方法でgetTypeを実装する方法があるので、それは既知のすべてのクラスをサポートしていますか?

編集:私たちはgsonに限定されません。別のライブラリがタスクを容易にする場合は、そのライブラリに切り替えることができます。私はそれをテストdidntの が、それは正しいようだ:

+2

これは[guava docs](https://github.com/google/guava/wiki/ReflectionExplained)で既に説明しています。クラスオブジェクトを使用しますが、名前で簡単に解決できます。あなたのアプローチでは、型の下限を取得することしかできないことに注意してください。 –

+0

@ M.Prokhorov確かに、私はグアバを使うことができました。クラス名からTypeを取得する例を提供できますか? – AlexC

答えて

3

GsonのTokenTypeは、静的なファクトリメソッドを持っており、あなたはこのようにそれを使用することができます。これはあなたを取得する必要があります

public Type getType(String name) { 
    try { 
     Class<?> clazz = Class.forName(typeName); 
     TypeToken<?> typeToken = TypeToken.get(clazz); 
     return typeToken.getType(); 
    } catch (ClassNotFoundException e) { 
     throw new IllegalArgumentException("Unsupported type: " + typeName, ce); 
    } 
} 

ジェネリックスやワイルドカード(またはワイルドカードがバインドされている場所)の大多数のケースでは、境界にあるパラメータ化された型を取得する必要があります。

免責事項:私はこれをテストしていません。

また、GuavaのバージョンTypeTokenをチェックしてください。

+0

これはコンパイルされませんでしたが、動作させるのは簡単でした。 – AlexC

+0

編集がすべての人に見えるようになると、私は同意します。 – AlexC

+1

奇妙なことに、同じシグネチャでダミーのインターフェイスを作成したときにコンパイルされました。コンパイルの問題は何でしたか? –

0

はこれを試してみてください

static Type getType(String name){ 
    return new TypeToken<Class.forName(name)>(){}.getType(); 
} 
+0

いいえ、これはコンパイルされません –

+0

コンパイルされませんでした。ありがとう! – AlexC

関連する問題