2012-02-16 14 views
39

私はRESTful APIを構築しており、JSONレスポンスで返すフィールドを選択するオプションを開発者に提供したいと考えています。 This blog postは、いくつかのAPI(Google、Facebook、LinkedIn)が開発者にどのようにレスポンスをカスタマイズできるかの例を示しています。これをパーシャルレスポンスと呼びます。Javaを使用して部分的なJSON応答を返す方法は?

の例では、次のようになります。

/users/123?fields=userId,fullname,title 

をAPI上記の例ではuserId、ユーザー「123」のためのfullNameとタイトルのフィールドを返す必要があります。

私はRESTful Webサービスでこれを実装する方法のアイデアを探しています。私は現在CXF(編集:とジャクソン)を使用していますが、JAX-RSの別の実装を試してみます。

ここに私の現在のものがあります。完全なUserオブジェクトを返します。 API呼び出し側が実行時に "fields"パラメタに基づいて欲しいフィールドだけを返すにはどうすればよいですか?私は他のフィールドをNullにしたくありません。私は単にそれらを返すことを望んでいません。

@GET 
@Path("/{userId}") 
@Produces("application/json") 
public User getUser(@PathParam("userId") Long userId, 
    @DefaultValue("userId,fullname,title") @QueryParam("fields") String fields) { 

User user = userService.findOne(userId); 

StringTokenizer st = new StringTokenizer(fields, ","); 
while (st.hasMoreTokens()) { 

    // here's where i would like to select only the fields i want to return 

} 
return user; 
} 

UPDATE:私は自分のドメインクラスに@JsonFilter("myFilter")を追加その情報でhttp://wiki.fasterxml.com/JacksonFeatureJsonFilter

:私はこれにリンクされているunludoのリンクをたどっ

。次に、RESTfulサービスメソッドを変更して、ユーザーの代わりにStringを返すようにしました。

@GET 
@Path("/{userId}") 
@Produces("application/json") 
public String getUser(@PathParam("userId") Long userId, 
        @DefaultValue("userId,fullname,title") @QueryParam("fields") String fields) { 

    User user = userService.findOne(userId); 

    StringTokenizer st = new StringTokenizer(fields, ","); 
    Set<String> filterProperties = new HashSet<String>(); 
    while (st.hasMoreTokens()) { 
     filterProperties.add(st.nextToken()); 
    } 

    ObjectMapper mapper = new ObjectMapper(); 
    FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", 
       SimpleBeanPropertyFilter.filterOutAllExcept(filterProperties)); 

    try { 
     String json = mapper.filteredWriter(filters).writeValueAsString(user); 
     return json; 
    } catch (IOException e) { 
     e.printStackTrace(); 
    return e.getMessage(); 
    } 
} 

これ以上のテストを行う必要があります。

+0

フィールドクエリパラメータオプションで大文字小文字を区別しないようにするにはどうすればよいですか? –

答えて

17

ジャクソン(私が信じるJava標準の偉大なJSONライブラリ)を使用している場合、@Viewアノテーションを使用して、結果のオブジェクトで必要なものをフィルタすることができます。

私はあなたが何かダイナミックなものをしたいと思うので少し複雑です。あなたはここで探しているものを見つけるでしょう:http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html(6を見てください。完全に動的フィルタリング:@JsonFilter)。

私はあなたが見つける解決策に興味があります。

+0

フィールドクエリパラメータオプションで大文字小文字を区別しないようにするにはどうすればよいですか? –

5

リクエストごとにリソースメソッド内にObjectMapperインスタンスを作成すると、パフォーマンス上のオーバーヘッドが大きくなる可能性があります。 the Jackson performance best practicesによると、オブジェクトマッパーは高価です。

代わりに、the Jackson 2.3 ObjectWriterModifier/ObjectReaderModifier featureを使用してリソースメソッド内でJAX-RSプロバイダのJacksonオブジェクトライターをカスタマイズすることができます。

リソースメソッド内で使用されているJAX-RS Jacksonプロバイダに適用されるフィルタのセットを変更するObjectWriterModifierスレッドローカルオブジェクトを登録する方法の例を示します。 JAX-RS実装に対してコードをテストしていないことに注意してください。

public class JacksonObjectWriterModifier2 { 

    private static class FilterModifier extends ObjectWriterModifier { 
     private final FilterProvider provider; 

     private FilterModifier(FilterProvider provider) { 
      this.provider = provider; 
     } 

     @Override 
     public ObjectWriter modify(EndpointConfigBase<?> endpoint, MultivaluedMap<String, Object> responseHeaders, 
            Object valueToWrite, ObjectWriter w, JsonGenerator g) throws IOException { 
      return w.with(provider); 
     } 
    } 

    @JsonFilter("filter1") 
    public static class Bean { 
     public final String field1; 
     public final String field2; 

     public Bean(String field1, String field2) { 
      this.field1 = field1; 
      this.field2 = field2; 
     } 
    } 

    public static void main(String[] args) throws IOException { 
     Bean b = new Bean("a", "b"); 
     JacksonJsonProvider provider = new JacksonJsonProvider(); 
     ObjectWriterInjector.set(new FilterModifier(new SimpleFilterProvider().addFilter("filter1", 
       SimpleBeanPropertyFilter.filterOutAllExcept("field1")))); 

     provider.writeTo(b, Bean.class, null, null, MediaType.APPLICATION_JSON_TYPE, null, System.out); 
    } 

} 

出力:

{"field1":"a"} 
+0

フィールドクエリパラメータオプションで大文字小文字を区別しないようにするにはどうすればよいですか? –

3

ライブラリジャージーエンティティフィルタリングはそれを行うことができます:

https://github.com/jersey/jersey/tree/2.22.2/examples/entity-filtering-selectable

https://jersey.java.net/documentation/latest/entity-filtering.html

Exemple:

マイオブジェクト

public class Address { 

    private String streetAddress; 
    private String region; 
    private PhoneNumber phoneNumber; 
} 

URL

人/ 1234?= streetAddress、地域

RETURN

{ 
    "streetAddress": "2 square Tyson", 
    "region": "Texas" 
} 

を選択

をMavenの対象に追加10
<dependency> 
    <groupId>org.glassfish.jersey.ext</groupId> 
    <artifactId>jersey-entity-filtering</artifactId> 
    <version>2.22.2</version> 
</dependency> 
+0

サードパーティのライブラリやプラグインへのリンクは、一般的にStack Overflowコミュニティによって悩まされています。 SOは、プログラミングコードをデバッグするのに役立つコードサンプルを得るために役立ちます。私はあなたの答えの素晴らしいフォーマットが好きです。 – Kmeixner

+0

フィールドクエリパラメータオプションで大文字小文字を区別しないようにするにはどうすればよいですか? –

関連する問題