9

クラスに注釈を付けられない (またはまったく変更できない) オブジェクトを宣言するためのツールとして Jackson を使用しています。クラスの 1 つに、型指定されていないリストのセッターとゲッターがあります。これがサニタイズされたバージョンです:

public class Family {
    private List members;
    public List getMembers() { return members; }
    public void setMembers(List members) { this.members = members; }
    //...many, many other properties
}

public class Member {
    private String name;
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

逆シリアル化しようとしている JSON は次のとおりです。

{ "members" : [ { "name" : "Mark" } ] }

私が使用する単純なコードは次のとおりです。

ObjectMapper mapper = new ObjectMapper();
Family family = mapper.readValue(json, Family.class);
Member member = (Member) family.getMembers().get(0);
System.out.println(member.getName());

Membersしかしもちろん、これは失敗します。Jackson はフォールバックの代わりに s のリストを作成することを知らなかったからLinkedHashMapです。

membersJackson にとして扱うように指示する最も簡単な方法は何List<Member>ですか? Jackson が適切に処理する他の多くのプロパティがあるため、クラスに完全にカスタムのデシリアライザーを使用したいとは思いません。

BeanDeserializerModifier を使用して、私が思いつくことができる最高のものを次に示します。

mapper.setDeserializerProvider(new StdDeserializerProvider()
  .withDeserializerModifier(new BeanDeserializerModifier() {
      @Override
      public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) {
          if (beanDesc.getBeanClass() == Family.class) {
            CollectionType type = CollectionType.construct(ArrayList.class, SimpleType.construct(Member.class));
            TypeDeserializer typeDeserializer = type.getTypeHandler();
            SettableBeanProperty.MethodProperty membersProperty = (SettableBeanProperty.MethodProperty) builder.removeProperty("members");
            builder.addProperty(new SettableBeanProperty.MethodProperty(
               "members",
               type,
               typeDeserializer,
               beanDesc.getClassAnnotations(),
               (AnnotatedMethod) membersProperty.getMember()
            ));
          }
          return builder;
      }}));

それは機能しますが、私がやろうとしていることは本当に低レベル(そして冗長!)のようです。ここで何が欠けていますか?

編集

私はJackson 1.8.2を使用していますが、やむを得ない理由がある場合は更新できます。

4

1 に答える 1

9

ミックスイン アノテーションは、私が見逃していたパズルの重要なピースでした。この問題を解決するためのよりクリーンな方法を次に示します。

ObjectMapper mapper = new ObjectMapper();
mapper.getDeserializationConfig().addMixInAnnotations(Family.class, FamilyMixin.class);

Family family = mapper.readValue(json, Family.class);
Member member = (Member) family.getMembers().get(0);

//...

interface FamilyMixin {
    @JsonDeserialize(contentAs = Member.class)
    void setMembers(List members);
}

mix-in アノテーションでできることは、制御下にあるプロキシにアノテーションを付けることです。その mix-in クラスが実際のクラスに適用されると、Jackson はそれらの注釈が実際のクラスのメンバーに注釈を付けたかのように動作します。

私の場合、JsonDeserialize.contentAs()コンテナーのコンテンツ タイプを指定するために使用します。しかし、ほとんどの注釈はこの方法を使用して利用できるはずです。

于 2012-05-31T21:09:06.877 に答える