28

ジャージーを使用して実装されたJAX-RSRESTサービスがあります。JAX-RS / Jerseyの優れた機能の1つは、いくつかのJavaアノテーションを振りかけるだけでPOJOをRESTサービスに簡単に変換できることです...JAXBアノテーションを使用してPOJOをJSONに変換するための非常に簡単なメカニズムを含みます。

ここで、このクールなJSON化機能をREST以外の目的で利用できるようにしたいと思います。これらのオブジェクトの一部を、JSONテキストとしてディスクにシリアル化できるようにしたいと思います。シリアル化するJAXBオブジェクトの例を次に示します。

@XmlRootElement(name = "user")
public class UserInfoImpl implements UserInfo {

    public UserInfoImpl() {} 

    public UserInfoImpl(String user, String details) {
        this.user = user;
        this.details = details;
    }

    public String getUser() { return user; }
    public void setUser(String user) { this.user = user; }

    public String getDetails() { return details; }
    public void setDetails(String details) { this.details = details; }

    private String user;
    private String details;
}

ジャージーは、追加情報なしでこれらの1つをjsonに変えることができます。ジャージーが私のようなニーズのためにAPIでこの機能を公開したかどうか疑問に思っていますか?私は今のところそれを見つけることができませんでした...

ありがとう!

UPDATE 2009-07-09:Providersオブジェクトを使用して、ほぼ正確にやりたいことができることを学びました。

  @Context Providers ps;
  MessageBodyWriter uw = ps.getMessageBodyWriter(UserInfoImpl.class, UserInfoImpl.class, new Annotation[0], MediaType.APPLICATION_JSON_TYPE);

  uw.writeTo(....)

...これにより、オブジェクトがjsonとして任意の出力ストリームに書き込まれます。これは私にとっては完璧ですが、@Componentオブジェクトから@Contextを使用してProvidersオブジェクトに到達することしかできません。通常の注釈のないPOJOからアクセスする方法を知っている人はいますか?ありがとう!

4

7 に答える 7

19

Jersey は、mapped()、bagerfish()、または natural() 表記を使用するかどうかに応じて、いくつかの異なるフレームワークを使用します。自然は通常、人々が望むものです。そして、これは非常に優れた (そして非常に高速な) スタンドアロンの Jackson JSON プロセッサを使用して実装されていると私は信じています。ただし、Jackson は独自の JAX-RS プロバイダーも提供しており、Object->JSON に直接アクセスできます。

実際、JAXB アノテーションのサポートも追加されました。見て

http://wiki.fasterxml.com/JacksonJAXBAnnotations

それが最終的にあなたが探しているものだと思います。Jackson は Object<->JSON 処理を行います...Jersey は呼び出しを行うだけです

于 2009-11-06T23:05:56.060 に答える
6

JAXB を使用してオブジェクトを JSON にマップする簡単な例を次に示します (Jackson を使用):

http://ondra.zizka.cz/stranky/programovani/java/jaxb-json-jackson-howto.texy

于 2009-11-22T15:46:44.473 に答える
5
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(pojoObject);
于 2011-11-02T10:49:31.400 に答える
3

JAXB アノテーションは、XML へのシリアライズ時に正常に機能します。主な問題は、JAXB が空の配列をサポートしていないことです。だから、このようなものをシリアライズすると...

List myArray = new ArrayList();

... jaxbアノテーションを介してjsonに変換すると、空の配列はすべて[]ではなくnullになります。

これを解決するには、pojos を jackson 経由で直接 json にシリアライズするだけです。

Jersey のユーザー ガイドからこれを見てみましょう: http://jersey.java.net/nonav/documentation/latest/user-guide.html#d0e1959

これは、JAXB なしで Jackson プロバイダーを使用する最良の方法です。さらに、ウェブから jackson-all-xyz-jar をダウンロードすることで、いつでも jackson の最新バージョンを使用できます。

この方法は jaxb アノテーションに干渉しないので、試してみることをお勧めします!

于 2010-11-17T14:39:37.207 に答える
1

ジャージーはJAX-RSのリファレンス実装であり、JAX-RSはRESTサービスのエンドポイントを実装する標準的な方法を提供することに完全に焦点を合わせているため、ペイロードのシリアル化の問題は他の標準に任されています。

JAX-RS標準にオブジェクトのシリアル化が含まれていると、すぐに大きな多頭の獣になり、実装が難しく、焦点の一部が失われると思います。

クリーンで使いやすいRESTエンドポイントの提供にJerseyがどれほど重点を置いているかを感謝します。私の場合、すべてのJAXB配管を含む親をサブクラス化したので、バイナリとXMLの間でオブジェクトをマーシャリングするのは非常にクリーンです。

于 2009-07-09T17:27:40.653 に答える
1

少しジャージー固有のブートストラップを使用すると、それを使用して必要な JSON オブジェクトを作成できます。次の依存関係を含める必要があります (バンドルを使用できますが、テストに Weld を使用している場合は問題が発生します)。

    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-json</artifactId>
        <version>1.12</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.12</version>
    </dependency>

そこから、JAXB アノテーション付きクラスを作成できます。次に例を示します。

@XmlRootElement
public class TextMessage {
private String text;
    public String getText() { return text; }
    public void setText(String s) { this.text = text; }
}

次に、次の単体テストを作成できます。

    TextMessage textMessage = new TextMessage();
    textMessage.setText("hello");
    textMessage.setUuid(UUID.randomUUID());

    // Jersey specific start
    final Providers ps = new Client().getProviders();
    // Jersey specific end
    final MultivaluedMap<String, Object> responseHeaders = new MultivaluedMap<String, Object>() {

        @Override
        public void add(final String key, final Object value) {
        }

        @Override
        public void clear() {
        }

        @Override
        public boolean containsKey(final Object key) {
            return false;
        }

        @Override
        public boolean containsValue(final Object value) {
            return false;
        }

        @Override
        public Set<java.util.Map.Entry<String, List<Object>>> entrySet() {
            return null;
        }

        @Override
        public List<Object> get(final Object key) {
            return null;
        }

        @Override
        public Object getFirst(final String key) {
            return null;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

        @Override
        public Set<String> keySet() {
            return null;
        }

        @Override
        public List<Object> put(final String key, final List<Object> value) {
            return null;
        }

        @Override
        public void putAll(
                final Map<? extends String, ? extends List<Object>> m) {
        }

        @Override
        public void putSingle(final String key, final Object value) {
        }

        @Override
        public List<Object> remove(final Object key) {
            return null;
        }

        @Override
        public int size() {
            return 0;
        }

        @Override
        public Collection<List<Object>> values() {
            return null;
        }
    };

    final MessageBodyWriter<TextMessage> messageBodyWriter = ps
            .getMessageBodyWriter(TextMessage.class, TextMessage.class,
                    new Annotation[0], MediaType.APPLICATION_JSON_TYPE);
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    Assert.assertNotNull(messageBodyWriter);

    messageBodyWriter.writeTo(textMessage, TextMessage.class,
            TextMessage.class, new Annotation[0],
            MediaType.APPLICATION_JSON_TYPE, responseHeaders, baos);
    final String jsonString = new String(baos.toByteArray());
    Assert.assertTrue(jsonString.contains("\"text\":\"hello\""));

このアプローチの利点は、JEE6 API 内にすべてが保持されることです。プロバイダーのテストと取得以外に、外部ライブラリは明示的に必要ありません。ただし、標準には何も提供されておらず、実際には使用しないため、MultivaluedMap の実装を作成する必要があります。また、 GSONよりも遅く、必要以上に複雑になる場合があります。

于 2012-05-30T12:35:36.977 に答える
0

私は XML ビューを理解していますが、標準装備として POJO の JSON サポートを要求するという先見の明があったでしょう。実装が JSON でクライアントが JavaScript RIA の場合、JSON 識別子を特殊文字で修正する必要はありません。

また、Java Beans が POJO ではないということではありません。Web層の外面で次のようなものを使用したいと思います:

public class Model
{
   @Property height;
   @Property weight;
   @Property age;
}

デフォルトのコンストラクターはなく、getter/setter ノイズもありません。独自の注釈を付けた POJO だけです。

于 2009-08-09T15:40:31.593 に答える