2013-12-13 12 views
13

Jersey 2.4を使用して、JSONオブジェクトを処理する簡単なRESTインターフェイスを作成しています。私の問題は、出力を制御するためにfasterxml Jacksonのアノテーションを使用しようとしていることです。これは私のためには機能しません。注釈をBeanクラスに入れましたが、無視されます。JerseyでJackson ObjectMapperを使用する

明示的にObjectMapperを作成し、これを使用してJava Beanを文字列化すると、Jackson出力を尊重する出力が得られます。しかし、私は、私のリソースクラスが単にBeanを返すことができるように、この手順を実行する必要はないことを望み、Jerseyフレームワークはそれを文字列化します。

私はこの回答をCustom ObjectMapper with Jersey 2.2 and Jackson 2.1から解決しようとしましたが、これは私のためには動作しません。 ContextResolverは作成されているが、決して呼び出されることはない。

私はまた、この明らかに単純な問題を解決しようと多くの時間を費やしました。私はこれを以下に示す非常に単純なテストケースに切り離しました。私はこれを解決するために何か助けに感謝します。

リソースのJavaクラス:

@Path("resource") 
public class MainResource { 

    public static class Foobar { 
     @JsonIgnore 
     private String foo = "foo"; 
     private String baa = "baa"; 
     private Map<String, List<? extends Number>> map = new HashMap<>(); 

     public Foobar() { 
      map.put("even", Arrays.asList(new Integer[] { 2, 4, 6, 8, 10 })); 
      map.put("odd", Arrays.asList(new Integer[] { 1, 3, 5, 7, 9 })); 
      map.put("float", Arrays.asList(new Float[] { 1.1F, 2.2F, 3.3F })); 
     } 

     public String getFoo() { 
      return foo; 
     } 

     public void setFoo(String foo) { 
      this.foo = foo; 
     } 

     public String getBaa() { 
      return baa; 
     } 

     public void setBaa(String baa) { 
      this.baa = baa; 
     } 

     @JsonAnyGetter 
     public Map<String, List<? extends Number>> getMap() { 
      return map; 
     } 

     public void setMap(Map<String, List<? extends Number>> map) { 
      this.map = map; 
     } 
    } 

    private ObjectMapper om = new ObjectMapper(); 

    @GET 
    @Path("get-object") 
    @Produces(MediaType.APPLICATION_JSON) 
    public Foobar getObject() { 
     // In this method, I simply return the bean object but the WRONG JSON syntax is generated. 
     return new Foobar(); 
    } 

    @GET 
    @Path("get-string") 
    @Produces(MediaType.APPLICATION_JSON) 
    public String getString() throws JsonProcessingException { 
     // This method returns the RIGHT JSON syntax but I don't want to have to explicitly use the ObjectMapper. 
     Foobar foobar = new Foobar(); 
     return om.writeValueAsString(foobar); 
    } 
} 

のweb.xml:

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 

    <module-name>sample</module-name> 

    <servlet> 
     <servlet-name>Jersey Web Application</servlet-name> 
     <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
     <init-param> 
      <param-name>jersey.config.server.provider.packages</param-name> 
      <param-value>ie.cit.nimbus.sample</param-value> 
     </init-param> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>Jersey Web Application</servlet-name> 
     <url-pattern>/*</url-pattern> 
    </servlet-mapping> 

</web-app> 

POMの依存関係:

<dependencies> 
    <dependency> 
     <groupId>com.fasterxml.jackson.jaxrs</groupId> 
     <artifactId>jackson-jaxrs-json-provider</artifactId> 
     <version>2.3.0</version> 
    </dependency> 
    <dependency> 
     <groupId>org.glassfish.jersey.ext</groupId> 
     <artifactId>jersey-spring3</artifactId> 
     <version>2.4.1</version> 
    </dependency> 
    <dependency> 
     <groupId>org.glassfish.jersey.media</groupId> 
     <artifactId>jersey-media-json-jackson</artifactId> 
     <version>2.4.1</version> 
    </dependency> 
</dependencies> 

答えて

1

ジャックスとジャクソンを統合する方法はたくさんあります-rsジャージーim保全。

Mkyongチュートリアルを見てみると:http://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/ web.xmlのinitパラメータに "POJomappingFeature" - > trueを渡す必要があるようです。 私はあなたの代わりに公式ジャージーのマニュアルを見てみる場合は

ジャージー1.8これはのために働くと思う: https://jersey.java.net/nonav/documentation/latest/user-guide.html#json.jackson あなたがJAX-RSプロバイダーを実装し、アプリケーションのリソース

にそのプロバイダを追加する必要があることを思わ
@Provider 
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> 

は、彼らはあなたに、私はこの方法を使用し、この https://github.com/jersey/jersey/blob/2.4.1/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/MyObjectMapperProvider.java

を行う方法の例を提供し、それは私のPROBを解決しましたレム、およびジャクソンの注釈は、ジャクソンのプロバイダによって正しくスキャンされます。

私はあなたがマップを初期化するために、あなたの豆でこの構文を使用することをお勧めトピックオフ

import static java.util.Arrays.asList; 

public static class Foobar { 
     @JsonIgnore 
     private String foo = "foo"; 
     private String baa = "baa"; 
     private Map<String, List<? extends Number>> map = new HashMap<>(){{ 
      put("even", asList(2, 4, 6, 8, 10)); 
      put("odd", asList(1, 3, 5, 7, 9)); 
      put("float", asList(1.1F, 2.2F, 3.3F)); 
     }}; 

     public Foobar() { 
     } 

     public String getFoo() { 
      return foo; 
     } 

     public void setFoo(String foo) { 
      this.foo = foo; 
     } 

     public String getBaa() { 
      return baa; 
     } 

     public void setBaa(String baa) { 
      this.baa = baa; 
     } 

     @JsonAnyGetter 
     public Map<String, List<? extends Number>> getMap() { 
      return map; 
     } 

     public void setMap(Map<String, List<? extends Number>> map) { 
      this.map = map; 
     } 
    } 
7

残念ながら、誰もがそれを必要以上に、これははるかに困難になります。彼らの知恵のジャージーチームはジャクソン1.9を統合することに決めました。

しかし、それはかなり簡単でした。ただ、この操作を行います。

<dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-databind</artifactId> 
     <version>2.3.0</version> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.jaxrs</groupId> 
     <artifactId>jackson-jaxrs-json-provider</artifactId> 
     <version>2.3.0</version> 
    </dependency> 

は今、この取り除く:

<dependency> 
    <groupId>org.glassfish.jersey.media</groupId> 
    <artifactId>jersey-media-json-jackson</artifactId> 
    <version>2.4.1</version> 
</dependency> 

は、その後、あなたのweb.xmlの変更でこの行:

<param-value>ie.cit.nimbus.sample</param-value> 

があるために:

<param-value>ie.cit.nimbus.sample,com.fasterxml.jackson.jaxrs.json</param-value> 

それはそれを行う必要があります。

+0

codehus感謝を使用していました。私はこれを試しましたが、それは何の違いも生じていないようです。これはまだfasterxmlアノテーションを無視し、間違ったJSON出力を生成します。変更が必要なことは他にありますか? – jcstockdale

+0

使用しようとしている注釈を教えてもらえますか?私はテストケースをセットアップします。 –

+0

あなたはJsonIgnoreアノテーションを意味しますか?プライベートフィールドではなく、ゲッターやセッターに置いてみてください。 –

11

EDIT:それはバグを(少なくともアンドロイドデバイスとし、詳細についてはEDIT2を参照)を生成として以下古いアプローチを使用しないでください。私のテストでは、Jersey v2.6は@Provideで問題を解決しているようですが、そのアプローチはうまくいきませんでした。私はこのシンプルなプロバイダで動作させることができました:

@Provider 
public class JerseyMapperProvider implements ContextResolver<ObjectMapper> { 
    private static ObjectMapper apiMapper = ObjectMapperManager.createMapperForApi(); 
    @Override 
    public ObjectMapper getContext(Class<?> type) 
    { 
     return apiMapper; 
    } 
} 

私のハックを下記から使用しないでください。

@Provider 
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> 

を使用して

が私のために働いていなかった


OLD APPROACH(ジャージー2.4 &ジャクソン2.3)と多分これはジャクソンプロバイダにによるものですが中にバグを報告しましたContextResolverJacksonJsonProvider.java(2.3rc1)に登録するコード:

@Override 
protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType) 
{ 
    if (_providers != null) { 
     ContextResolver<ObjectMapper> resolver = _providers.getContextResolver(ObjectMapper.class, mediaType); 
     /* Above should work as is, but due to this bug 
     * [https://jersey.dev.java.net/issues/show_bug.cgi?id=288] 
     * in Jersey, it doesn't. But this works until resolution of 
     * the issue: 
     */ 
     if (resolver == null) { 
      resolver = _providers.getContextResolver(ObjectMapper.class, null); 
     } 
     if (resolver != null) { 
      return resolver.getContext(type); 
     } 
    } 
    return null; 
} 

少なくとも私はhttps://jersey.dev.java.net/issues/show_bug.cgi?id=288にアクセスできないので、このバグについてはわかりません。

しかし、私は回避策を見つけました(もしそうならハック)。ただ、適切なアノテーションでJacksonJsonProviderを拡張し、このようなあなたのObjectMapperを返します(それはあなたがJSONのRESTサービスに初めてアクセスするときに登録されます、ログで確認してください)、それが自身を登録します何もする

@Provider 
@Consumes(MediaType.APPLICATION_JSON) // NOTE: required to support "non-standard" JSON variants 
@Produces(MediaType.APPLICATION_JSON) 
public class JacksonHackProvider extends JacksonJsonProvider { 
    @Override 
    protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType) { 
     return new MyCustomObjectMapper(); 
    } 
} 

必要はありません。これは今、私のために働いている、エレガントではないが、私はあきらめた。

EDIT:このハックに関連したバグを経験しています。AndroidボレーはリクエストボディでPOST/PUTリクエストを送信できず、常にフレームワークから400を取得しています。

EDIT2:このハックは、ボレーのAndroidアプリとOKHTTPクライアントがPOSTまたはPUTリクエストを試行しようとしたときにいつもジェネリック400を担当していました。テストジャージ2ではこれを使用しないでください。

私はObjectMapperにして@Autowireにこれを使用
package com.example.api.environment.configs; 

import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.SerializationFeature; 
import com.fasterxml.jackson.datatype.joda.JodaModule; 

import javax.ws.rs.ext.ContextResolver; 
import javax.ws.rs.ext.Provider; 

@Provider 
public class JacksonConfig implements ContextResolver<ObjectMapper> { 

    private final ObjectMapper objectMapper; 

    public JacksonConfig() { 
    objectMapper = new ObjectMapper() 
      .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) 
      .registerModule(new JodaModule()); 
    }; 

    @Override 
    public ObjectMapper getContext(Class<?> type) { 
    return objectMapper; 
    } 
} 

:一つだけObjectMapperを作成する必要があります6あなたは@ProvideアプローチJersey 2.13を使用して

+0

使用している 'ObjectMapperManager'クラスは何ですか?それはあなたのものですか? –

+0

カスタムのファクトリクラスだけを置き換えることができます。 'new ObjectMapper()' – for3st

+0

カスタムファクトリクラスだけを置き換えることができます。 'new ObjectMapper()' – for3st

5

を使用することができますので、これを修正するようですが、あなたは同じObjectMapperを使用するように@Providerを強制することができますその場で文書json-schemaを生成してください。

+0

あなたは、春に他のすべてのクラスに感染することなく、ソリューションを使用できますか? –

+0

@AndréSchild:done。 – Nthalk

-1

この

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) 
public class Event { 
    ----- 
    -- 
} 

のように各モデルクラスに追加し、それは私のために働いたが、私はジャクソンの瓶

+0

リンクを参照してください:http://stackoverflow.com/help/how-to-answer – Vikrant

関連する問題