2012-02-21 12 views
11

実行時に@JsonFilterアノテーションがいつ使用されるのかを選択的に判断できますか?@JsonFilterは "JsonMappingException:BeanPropertyFilterを解決できません"をスローします

フィルタを用意していないときは、JsonMappingException例外が発生します(下記参照)。

背景:

私は動的にシリアライズされた取得Beanプロパティをフィルタリングする@JsonFilterを使用することができますrecent StackOverflow postから学びました。これは素晴らしいです。

// shortened for brevity 
FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.filterOutAllExcept(filterProperties)); 

return mapper.filteredWriter(filters).writeValueAsString(user); 

問題:自分のドメインクラスに、私のJAX-RSサービスでこのコード(CXF実装を使用)を添加した@JsonFilter("apiFilter")を追加した後、私は動的に私のRESTfulなAPIによって返されるプロパティをフィルタリングすることができています私はフィルターをまったく適用したくないさまざまなサービスコールがあります。そのような場合は、プロパティをフィルタリングせずにドメインクラス全体を返したいと思います。私は次のように私は例外を取得していたドメインクラスを返すようにしようとする場合には:

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not resolve BeanPropertyFilter with id 'apiFilter'; no FilterProvider configured 

at org.codehaus.jackson.map.ser.BeanSerializer.findFilter(BeanSerializer.java:252) 
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFieldsFiltered(BeanSerializer.java:216) 
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:140) 

答えて

6

私はあなたがすべてのプロパティをしたい場合のために、空のシリアル化フィルタを定義するフィルタライターをだますことができると思いますseralized:エンジンが@JsonFilter注釈で定義された「apiFilter」フィルタを探し

FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.serializeAllExcept(emptySet)); 

この方法では、それはそれを見つけたが、それは(すべてのプロパティをシリアル化しますと)何の効果もありません。また、あなたの代わりにfilteredWriter()のファクトリメソッドwriter()

EDIT を呼び出すことができます。

ObjectWriter writer=null; 
if(aplyFilter) { 
    FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.filterOutAllExcept(filterProperties)); 
    writer=mapper.filteredWriter(filters); 
} else { 
    writer=mapper.writer(); 
} 

return writer.writeValueAsString(user); 

私はこの最後のソリューションは道クリーナー、そして確かに優れていると思います。

+0

あなたの編集した例では、すべてのjax-rsサービスコールでどのライターメソッドを呼び出すかをチェックするコードを含める必要がありますか?いくつかのサービスメソッドでは、私はStringではなく実際のUserオブジェクトを返します。多くのあなたのご意見ありがとうございます! – Justin

+1

私はそれを試してみる機会がありました。あなたが提案した "トリック"は動作しますが、私はあなたの2番目の "クリーンな"提案を得ることができませんでした。その場合、私はまだ "No FilterProvider configured"エラーを受け取ります。再度、感謝します。 – Justin

+0

@ジャスティン:まあ、IMO問題を解決する「汚れた」回避策は、うまくいかない「きれいな」解決策よりも優れています。あなたの問題を解決するのに役立つことを願っています。 –

18

私はそれが既に回答されていますが、任意の新しい仲間のためにジャクソンが実際に欠落しているフィルタ(JACKSON-650)で失敗しないための機能を追加しました知っている:あなたはちょうど SimpleFilterProvider.setFailOnUnknownId(false)を呼び出すために、あなたは、この例外を取得することはありません必要

+0

お返事ありがとうございます。これは役に立ちます – Justin

+4

もちろん、使用しているマッパーでフィルタリングをまったく使用しない場合でも、SimpleFilterProviderを設定する必要があります。しかたがない。 – Jules

0

私は同じ例外を受けて同じ問題が発生しましたが、受け入れられた答えは私の場合は本当に助けになりませんでした。ここでは私のために働いたソリューションです:私のセットアップで

私はこのようなカスタムJacksonSerializerを使用していました:

@JsonSerialize(using = MyCustomSerializer.class) 
private Object someAttribute; 

そして、そのシリアライザは、次のように実装されました:

public class MyCustomSerializer extends JsonSerializer<Object> { 
    @Override 
    public void serialize(Object o, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
    if (o != null) { 
     jgen.writeObject(o); 
    } 
    } 
} 

これに伴う問題フィルタを使用しない限り、それは機能します。プリミティブをシリアル化する場合にも機能します。たとえば、jgen.writeString(..)を使用する場合などです。フィルタを使用すると、そのコードは、JsonGeneratorではなく、SerializerProviderの中に保存されているため、間違っています。その場合、jsongeneratorを直接使用すると、フィルタを知らない新しいSerializerProviderが内部的に作成されます。したがって、短いjgen.writeObject(o)の代わりにprovider.defaultSerializeValue(o, jgen)に電話する必要があります。これにより、フィルターが失われずに適用できるようになります。

関連する問題