14

私の基本的な質問: 既にこれを自動的に行うように構築されたものはありますか (人気のあるライブラリ/パッケージの一部である必要はありません)? 私が扱っている主なものは、Spring (MVC) と Jackson2 です。

これを行うにはいくつかの手動の方法があることを理解しています:

  1. 特定のプロパティをproperty=value&形式にシリアル化するメソッドを各クラスに作成します (ロジックの重複が多いため、一種の悪臭を放ちます)。
  2. オブジェクトを受け入れる関数を作成し、リフレクションを使用してすべてのプロパティを動的に読み取り (ゲッターだと思います)、それぞれを取得して文字列を作成します。これが、ジャクソンがシリアライゼーション/デシリアライゼーションで一般的にどのように機能するかを想定していますが、実際にはわかりません。
  3. Jackson のいくつかの機能を使用して、オブジェクトをカスタムでシリアル化します。私はカスタムシリアライザーを調査しましたが、それらはクラスに固有のものであるようです (そのため、シリアライズしようとしているクラスごとに 1 つ作成する必要があります)、一般的な方法を望んでいました。オブジェクトに普遍的に適用する方法を理解するのに苦労しています。リンクのいくつか:
  4. を使用し、のキーと値のペアをObjectMapper.convertValue(object, HashMap.class);反復処理して、文字列を作成します (これは私が現在使用しているものですが、変換が過剰に感じますか?)。HashMap
  5. 他にも考えていないことがあると思います。

私が調べた主な投稿はJavaです:クラスのプロパティを取得して文字列表現を構築する

私のポイントは、それぞれに特定のものを指定しなくてもシリアル化できるようにしたいいくつかのクラスがあるということです。そのため、リフレクションを使用する関数 (上記の #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(Spring) を使用して別のサーバーに GET 要求を行い、特定のオブジェクトのプロパティ/値を URL に渡したいということです。次のようなものを使用できることを理解しています:

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

プロパティは自動的にマップされると思います。しかし、前述のように、オブジェクト タイプごとに異なる URL テンプレートとメソッドを作成する必要はありません。私は次のようなものを望んでいます:

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

SERIALIZE_URI私がそれを処理する場所はどこですか。getRequest("whatever", C1Object);と のように呼ぶことができますgetRequest("whateverElse", C2Object);

4

2 に答える 2

18

解決策 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;
}
于 2013-08-23T20:25:00.873 に答える
3

c1を持ってみましょう。

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

c1を URI に変換します

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

私たちが持った後

    http://test.com?c1prop1=C1prop1&c1prop2=C1prop2&c1prop3=C1prop3
于 2016-12-09T15:10:28.730 に答える