web-dev-qa-db-ja.com

ソースコードを制御できないプロパティを無視するようにジャクソンに伝えるにはどうすればよいですか?

要するに、私のエンティティの1つに GeometryCollection があり、これが「getBoundary」を呼び出すと例外をスローします(この理由は別の本です。

特定のゲッターを含めないようにジャクソンに伝える方法はありますか?コードを所有/制御するときに@JacksonIgnoreを使用できることを知っています。しかし、これはそうではありません。ジャクソンは、親オブジェクトの継続的なシリアル化を通じてこのポイントに到達しなくなります。 jacksonのドキュメントにフィルタリングオプションがありました。それはもっともらしい解決策ですか?

ありがとう!

102
maverick

Jackson Mixins を使用できます。例えば:

class YourClass {
  public int ignoreThis() { return 0; }    
}

このMixinで

abstract class MixIn {
  @JsonIgnore abstract int ignoreThis(); // we don't need it!  
}

これとともに:

objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);

編集:

Jackson 2.5+のコメントのおかげで、APIが変更されました。objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)で呼び出す必要があります

146
Amir Raminfar

もう1つの可能性は、不明なプロパティをすべて無視する場合、マッパーを次のように構成できることです。

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
61
laloumen

Javaクラスを使用

new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

注釈を使用

@JsonIgnoreProperties(ignoreUnknown=true)
24

注釈ベースのアプローチの方が優れています。しかし、時には手動操作が必要です。この目的のためにwithoutObjectWriterのメソッドを使用できます。

ObjectMapper mapper   = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
ObjectWriter writer   = mapper.writer().withoutAttribute("property1").withoutAttribute("property2");
String       jsonText = writer.writeValueAsString(sourceObject);
8
Fırat KÜÇÜK

既に述べたように、ここでミックスインアノテーションは非常にうまく機能します。プロパティごとの@JsonIgnoreを超える別の可能性は、含めるべきではない型がある場合(つまり、GeometryCollectionプロパティのすべてのインスタンスを無視する必要がある場合)に@JsonIgnoreTypeを使用することです。次に、タイプを制御する場合は直接追加するか、次のようにミックスインを使用します。

@JsonIgnoreType abstract class MixIn { }
// and then register mix-in, either via SerializationConfig, or by using SimpleModule

これは、すべてが単一の 'IgnoredType getContext()'アクセサーを持つクラスが多数ある場合に便利です(多くのフレームワークの場合)

8
StaxMan

私は同様の問題を抱えていましたが、それはHibernateの双方向の関係に関連していました。私が扱っていた見解に応じて、関係の一方を示し、プログラムで他方を無視したかった。それができない場合、厄介なStackOverflowExceptionsになります。たとえば、これらのオブジェクトがあった場合

public class A{
  Long id;
  String name;
  List<B> children;
}

public class B{
  Long id;
  A parent;
}

Aを見ている場合はBのparentフィールドをプログラムで無視し、Bを見ている場合はAのchildrenフィールドを無視します。

私はこれを行うためにミックスインを使い始めましたが、それはすぐに恐ろしくなります。データをフォーマットするためだけに存在する非常に多くの役に立たないクラスがあります。これをよりクリーンな方法で処理するために、独自のシリアライザーを作成することになりました: https://github.com/monitorjbl/json-view

無視するフィールドをプログラムで指定できます。

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(JsonView.class, new JsonViewSerializer());
mapper.registerModule(module);

List<A> list = getListOfA();
String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(B.class, match()
        .exclude("parent")));

また、ワイルドカードマッチャーを使用して、非常に単純化されたビューを簡単に指定できます。

String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(A.class, match()
        .exclude("*")
         .include("id", "name")));

私の元のケースでは、このような単純なビューの必要性は、親/子に関する最低限の情報を表示することでしたが、ロールベースのセキュリティにも役立ちました。オブジェクトに関するより少ない情報を返すために必要なオブジェクトの特権の少ないビュー。

これらはすべてシリアライザーからのものですが、アプリではSpring MVCを使用していました。これらのケースを適切に処理するために、既存のSpringコントローラークラスにドロップできる統合を作成しました。

@Controller
public class JsonController {
  private JsonResult json = JsonResult.instance();
  @Autowired
  private TestObjectService service;

  @RequestMapping(method = RequestMethod.GET, value = "/bean")
  @ResponseBody
  public List<TestObject> getTestObject() {
    List<TestObject> list = service.list();

    return json.use(JsonView.with(list)
        .onClass(TestObject.class, Match.match()
            .exclude("int1")
            .include("ignoredDirect")))
        .returnValue();
  }
}

どちらもMaven Centralで利用できます。これが他の誰かの助けになることを願っています。これはジャクソンにとって特にい問題であり、私の場合には良い解決策がありませんでした。

5
monitorjbl

クラスの特定のプロパティを常に除外する場合は、setMixInResolverメソッドを使用できます。

    @JsonIgnoreProperties({"id", "index", "version"})
    abstract class MixIn {
    }

    mapper.setMixInResolver(new ClassIntrospector.MixInResolver(){
        @Override
        public Class<?> findMixInClassFor(Class<?> cls) {
            return MixIn.class;  
        }

        @Override
        public ClassIntrospector.MixInResolver copy() {
            return this;
        }
    });
0
fifman

ここでもう1つの良い点は、@JsonFilterを使用することです。詳細はこちら http://wiki.fasterxml.com/JacksonFeatureJsonFilter