10

オブジェクトを JSON にシリアル化する次の Jackson/Java コードでは、次のようになります。

{"animal":{"x":"x"}}

しかし、私が実際に取得したいのはこれです:

{"dog":{"x":"x"}}

「動物」の代わりにオブジェクトの実行時タイプ (「犬」、「猫」) を取得するために、AnimalContainer に対してできることはありますか? (編集: マップ名は getter- および setter- メソッド名に由来することを認識しています。)私が考えることができる唯一の方法は、AnimalContainer 内で Animal の各タイプの属性を持ち、setter と getter を持つことです。一度に 1 つだけが評価されるようにします。しかし、これは Animal スーパークラスを持つ目的に反しており、間違っているように見えます。私の実際のコードには、「犬」と「猫」だけでなく、実際には十数個のサブクラスがあります。これを行うためのより良い方法はありますか (おそらく何らかの形で注釈を使用します)? 逆シリアル化のソリューションも必要です。

public class Test
{
   public static void main(String[] args) throws Exception
   {
      AnimalContainer animalContainer = new AnimalContainer();
      animalContainer.setAnimal(new Dog());

      StringWriter sw = new StringWriter();   // serialize
      ObjectMapper mapper = new ObjectMapper(); 
      MappingJsonFactory jsonFactory = new MappingJsonFactory();
      JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw);
      mapper.writeValue(jsonGenerator, animalContainer);
      sw.close();
      System.out.println(sw.getBuffer().toString());
   }
   public static class AnimalContainer
   {
      private Animal animal;
      public Animal getAnimal() {return animal;}
      public void setAnimal(Animal animal) {this.animal = animal;}
   }
   public abstract static class Animal 
   {
      String x = "x";
      public String getX() {return x;}
   }
   public static class Dog extends Animal {}
   public static class Cat extends Animal {} 
}
4

3 に答える 3

11

この発表によると、Jackson 1.5 は完全なポリモーフィック型処理を実装しており、トランクにはそのコードが統合されています。

これを機能させるには、次の 2 つの簡単な方法があります。

  • スーパータイプ (ここでは Animal) に @JsonTypeInfo アノテーションを追加する、または
  • ObjectMapper.enableDefaultTyping() を呼び出してオブジェクト マッパーを構成します (ただし、その場合、Animal は抽象型である必要があります)。
于 2010-02-08T02:02:39.357 に答える
2

これはおそらくあなたが探している答えではありませんが、Jackson バージョン 1.4 かそこら (つまり、次の 1.3 ではなく、1 つ後それ)。

現在のバージョンでは、カスタムのシリアライザー/デシリアライザーを実装する必要があります: 私はおそらく、デシリアライゼーション用にファクトリ メソッドを定義し、シリアライザー用に型ゲッターを定義します (「getAnimalType」などを抽象基本クラスで抽象として定義し、サブクラスでオーバーライドします-または基底クラスに実装するだけでも、インスタンスクラスのクラス名を出力?)

とにかく、念のため、JSON を使用してスキーマ言語を使用せずにサブクラスの処理を実装する際の根本的な問題を次に示します (json には実際に広く使用されているものがないため)。

  • データ (Bean プロパティ値) をメタデータ (適切なサブクラスを構築するためにのみ必要な型情報) から分離する方法 -- 分離しておく必要がありますが、形式としての JSON は定義する方法がありません (命名規則を使用できます)
  • そのようなメタデータを生成して使用するための適切な注釈を追加する方法。言語固有の機能に依存せずに (たとえば、Java クラス名に関連付ける必要はありません)

これらは解決可能な問題ですが、簡単に解決できるものではありません。:-)

于 2009-09-12T01:03:00.737 に答える
0

これは私がそれをするために考えることができる唯一の方法であり、それは醜いです。もっと良い方法はありますか?

   @JsonWriteNullProperties(false)
   public static class AnimalContainer
   {
      private Animal animal;

      public Animal getCat()
      {
         return animal instanceof Cat ? animal : null;
      }
      public void setCat(Cat cat)
      {
         this.animal = cat;
      }
      public Animal getDog()
      {
         return animal instanceof Dog ? animal : null;
      }
      public void setDog(Dog dog)
      {
         this.animal = dog;
      }
      public Animal getFish()
      {
         return animal instanceof Fish ? animal : null;
      }
      public void setFish(Fish fish)
      {
         this.animal = fish;
      }
   }
于 2009-08-25T13:57:54.107 に答える