2013-08-23 5 views
9

私の基本的な質問:すでにこれを自動的に行っているものはありますか?(一般的なライブラリ/パッケージの一部である必要はありません)私が扱っている主なものはSpring(MVC)とJackson2です。どのオブジェクトをURIに直列化するのですか?

私はこれを行うには、いくつかのマニュアルの方法があります理解:

  1. それがロジックの重複の束だからproperty=value&フォーム臭いの(種類にその特定のプロパティをシリアル化し、各クラスのメソッドを作成し、私が感じます)。
  2. オブジェクトを受け入れる関数を作成し、リフレクションを使用してすべてのプロパティを動的に読み込み(ゲッターと推測します)、それぞれを取得して文字列を構築します。私は、これが一般的なシリアライゼーション/デシリアライゼーションのためにジャクソンがどのように動作するかを仮定していますが、実際には分かりません。
  3. ジャクソンのいくつかの機能を使用して、オブジェクトをカスタムでシリアル化します。私はカスタム・シリアライザを研究しましたが、それはクラスに固有のようです(シリアル化しようとしている各クラスのクラスを作成する必要があります)。私は単なる普遍的にオブジェクトに適用する方法を理解するのが難しいです。リンクの数:
  4. 使用ObjectMapper.convertValue(object, HashMap.class);は、HashMapのキー/値のペアを反復し、私が今使っている何である(文字列を作成ですが、変換が過度であると感じていますか?)。
  5. 私は考えていない人がいると思います。

私がに見てきた主要ポストはJava: Getting the properties of a class to construct a string representation

私のポイントは、私はそれぞれに固有のものを指定しなくてシリアライズすることができるようにしたいいくつかのクラスを持っているということです。だからこそ、私はリフレクション(上記#2)を使って関数を処理する唯一の方法だと思っています(手動で行う必要がある場合)。

ことができます場合は、私が何を意味するかの例では、この2つのクラス、たとえば、である:

public class C1 { 
    private String C1prop1; 
    private String C1prop2; 
    private String C1prop3; 

    // Getters and setters for the 3 properties 
} 

public class C2 { 
    private String C2prop1; 
    private String C2prop2; 
    private String C2prop3; 

    // Getters and setters for the 3 properties 
} 

(なし、プロパティ名と規則は、私の実際のアプリが使用しているものではありません、それだけです例)

シリアライズの結果はC1prop1=value&C1prop2=value&C1prop3=valueC2prop1=value&C2prop2=value&C2prop3=valueですが、シリアライゼーションの仕組みを定義する場所は1つだけです(既に定義済み、または私が手動で作成したもの)。

だから、私の考えは、私は(私は上記のリンク先のポストから取った)次の形式を使用して終了しなければならないことである。

public String toString() { 
    StringBuilder sb = new StringBuilder(); 
    try { 
     Class c = Class.forName(this.getClass().getName()); 
     Method m[] = c.getDeclaredMethods(); 
     Object oo; 
     for (int i = 0; i < m.length; i++) 
     if (m[i].getName().startsWith("get")) { 
      oo = m[i].invoke(this, null); 
      sb.append(m[i].getName().substring(3) + ":" 
         + String.valueOf(oo) + "\n"); 
     } 
    } catch (Throwable e) { 
     System.err.println(e); 
    } 
    return sb.toString(); 
} 

とオブジェクトを受け入れ、そして形式を変更するように変更StringBuilderに追加されたアイテムのうちそれは私のために働く、私は今これを変更する助けを必要としません。

私の主な質問は、たとえ各プロパティと値を扱う方法を指定する必要があるとしても、私が上記の関数を(すぐに)変更するのではなく、この(潜在的に単純な)シリアル化を既に処理しているものがあるかどうかですどのようにそれぞれを組み合わせるのですか?

私がRestTemplate(春)を使って別のサーバーにGETリクエストを行い、そのURLに特定のオブジェクトのプロパティ/値を渡したいという背景があります。私はプロパティが自動的にマッピングされると信じて

restTemplate.getForObject("URL?C1prop1={C1Prop1}&...", String.class, C1Object); 

:私はのようなものを使用することができます理解しています。しかし、私が言ったように、私は、オブジェクトタイプごとに異なるURLテンプレートとメソッドを作る必要はありません。私は次のようなものを持っていることを望んだ:私はそれを処理したいところSERIALIZE_URIがある

public String getRequest(String url, Object obj) { 
    String serializedUri = SERIALIZE_URI(obj); 
    String response = restTemplate.getForObject("URL?" + serializedUri, String.class); 
    return response; 
} 

。そして、私はそれをgetRequest("whatever", C1Object);getRequest("whateverElse", C2Object);のように呼ぶことができます。

答えて

12

解決策4は問題ありません。理解してクリアするのは簡単です。

私は@JsonAnySetter注釈を使用することができる同様のソリューションを提案します。例えば、下記をご覧ください:プログラムを印刷の上

import com.fasterxml.jackson.annotation.JsonAnySetter; 
import com.fasterxml.jackson.databind.ObjectMapper; 

public class JacksonProgram { 

    public static void main(String[] args) throws Exception { 
     C1 c1 = new C1(); 
     c1.setProp1("a"); 
     c1.setProp3("c"); 

     User user = new User(); 
     user.setName("Tom"); 
     user.setSurname("Irg"); 

     ObjectMapper mapper = new ObjectMapper(); 
     System.out.println(mapper.convertValue(c1, UriFormat.class)); 
     System.out.println(mapper.convertValue(user, UriFormat.class)); 
    } 
} 

class UriFormat { 

    private StringBuilder builder = new StringBuilder(); 

    @JsonAnySetter 
    public void addToUri(String name, Object property) { 
     if (builder.length() > 0) { 
      builder.append("&"); 
     } 
     builder.append(name).append("=").append(property); 
    } 

    @Override 
    public String toString() { 
     return builder.toString(); 
    } 
} 

prop1=a&prop2=null&prop3=c 
name=Tom&surname=Irg 

そして、あなたのGetRequest方法は、次のようになります。

public String getRequest(String url, Object obj) { 
    String serializedUri = mapper.convertValue(obj, UriFormat.class).toString(); 
    String response = restTemplate.getForObject(url + "?" + serializedUri, String.class); 
    return response; 
} 
+3

**非常に興味深い**とクールになります後URI

UriComponentsBuilder.fromHttpUrl("http://test.com") .queryParams(new ObjectMapper().convertValue(c1, LinkedMultiValueMap.class)) .build() .toUri()); 

にC1を変換します。他の提案がない限り、私はこれと一緒に行くつもりです。私は#4がかなり良かったことに同意する - 私はそれが舞台裏で#2を推測していると推測しているので、それを保つかもしれない(私はこのソリューションが本当に好きなので除いて:))。 – Ian

+0

私はそれを聞いてうれしい。それを自由に使用してください。 Jacksonは信頼性が高く高速ですので、Jacksonのライブラリからできるだけ多くのソースコードを再利用する必要があります。 URLエンコーディングやそのようなことについても覚えておく必要があります。 –

+0

クール、感謝します。この答えはまさに私が探していたものです。私が知らなかったジャクソンの特徴です(私はライブラリについて十分に知っていない、または利用していないためです)。私はそれが適用可能かどうかわかりませんが、@ JsonViewを使用するように思われましたが、別の方法かもしれません。このシナリオで使用する方法や、ソリューションと比較して使用する理由を理解していますか? – Ian

2

たちはC1を持っています。

c1.setC1prop1("C1prop1"); 
c1.setC1prop2("C1prop2"); 
c1.setC1prop3("C1prop3"); 

我々は

http://test.com?c1prop1=C1prop1&c1prop2=C1prop2&c1prop3=C1prop3 
+0

これはうまくいきますが、これは春のフレームワークを使用しているか、それらのライブラリにアクセスできる場合にのみ役に立ちます。 – njfife

関連する問題