2012-03-09 8 views
3

私はJavaでPlay Framework 1.2.4を使用しており、JPAを使用してデータベースオブジェクトを永続化しています。 JSONとしてレンダリングされるいくつかのModelクラスがあります。しかし問題は、これらのJSONレスポンスをカスタマイズし、JSONとしてレンダリングする直前にオブジェクトを単純化したいということです。Play Framework:カスタムJSONオブジェクトのレンダリング

例えば、私はComplexClassという名前のオブジェクトがあり、id、name、property1、...、propertyNのプロパティを持っているとします。 JSONレスポンスでは、idフィールドとnameフィールドだけを表示したいと思います。

これを行う最もエレガントな方法は何ですか?カスタムバインダーオブジェクトを書くか、テンプレートを使用するなどの単純なJSONマッピングがありますか?

答えて

6

FlexJSONを使用して、それは本当に簡単です。これにより、必要なフィールドを組み込む/除外できるJSONSerializerを作成することができます。

Playで使用する例については、this articleをご覧ください。フレームワーク。あなたがそうのようなあなたのdependencies.ymlに追加することができ

public ComplexClass { 
    public Long id; 
    public String name; 
    // And lots of other fields you don't want 

    public String toJsonString() { 
    // Include id & name, exclude all others. 
    JSONSerializer ser = new JSONSerializer().include(
      "id", 
      "name", 
    ).exclude("*"); 
    return ser.serialize(this); 
    } 

}

:ここ
は簡単な例です

require: 
    - play 
    - net.sf.flexjson -> flexjson 2.1 

私が通常行うと、その実装モデルのためのインタフェースを記述していますコントローラのrenderJSON(someModel.toJSONString())に電話できるように、toJSONString()メソッドを使用します。

Link to official website

EDIT:リスト/コレクション

[OK]をエキストラたとえば、あなたがリストをシリアライズ起動したときにあなたには、いくつかの予期しない結果を得る可能性があります。これは、評価のの順序が重要であるためです。最初のinclude()またはexclude()は、次のものよりも優先されます。

親エンティティの子を直列化する例です(OneToMany関係)。 *

JSONSerializer ser = new JSONSerializer(); 
// Exclude these standard fields from childs 
ser.exclude(
    "*.persistent", 
    "*.class", 
    "*.entityId" 
); 
// Include childs and all its other fields 
ser.include(
    "childs", 
    "childs.*" 
); 
// Exclude everything else 
ser.exclude("*"); 
String data = ser.serialize(parent); 

は道によってワイルドカードです。このドキュメントは完全に説明しています。
*.classの除外は、どのパスの深度にも一致します。したがって、flexjsonが "foo.bar.class"のパスでフィールドをシリアライズしている場合は、*.class*はfoo.barと一致します。

+1

は、あなたの優雅な答えをありがとうございました。私はそれを試してみましょう。同じデータに対して複数のビューを作成する方がはるかに簡単であるため、FlexJsonは使いやすいと思います。 – huzeyfe

+0

ところで、(可能であれば)インターフェイスの詳細について少し詳しく説明できるので、オブジェクトリストのシリアル化も必要になるので、コントローラでこの方法を使用することもできます。 – huzeyfe

+1

リストの例で更新しました:) – maartencls

8

Play Framework 1.2.4はgsonライブラリに直接依存していますので、JSON文字列のレンダリングに使用できます。 gsonの@Expose注釈を使用するだけです。だからあなたの例では、あなたがこのようなあなたのJSON文字列にするフィールドをマークします:

public class ComplexClass { 

    @Expose 
    public Long id; 

    @Expose 
    public String name; 

    ... 
} 

次に、あなたのコントローラでは、あなただけにこれを行うだろう:

public static void someActionMethod() { 
    // get an instance of your ComplexClass here 
    ComplexClass complex = ... 
    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() 
    String json = gson.toJson(complex); 
    renderJson(json); 
} 

は、ドキュメントhereを参照してください。

ComplexClassが実際にplay.db.jpa.Modelであるためidフィールドは、親クラスに抽象化され、あなたがそれに@Expose注釈を入れることができない場合は、でアノテートされていないフィールドをスキップし、独自のExclusionStrategyを作成することができます@Exposeであり、idとは呼ばれません。したがって、このような何か(擬似コード):

public final class ComplexClassExclusionStrategy implements ExclusionStrategy { 

    public boolean shouldSkipField(FieldAttributes attributes) { 
     if (name of field is "id") return false; 
     if (field is annotated with @Expose) return false; 
     return true; 
    } 

そして、コントローラは、このように見えるように、わずかに変更されます:

GsonBuilder builder = new GsonBuilder(); 
    ComplexClassExclusionStrategy strategy = new ComplexClassExclusionStrategy(); 
    builder.setExclusionStrategies(strategy); 
    Gson gson = builder.create(); 
    String json = gson.toJson(complex); 
    renderJson(json); 
+0

ありがとうございました。 PlayがすでにGsonライブラリを使用しているため、プロジェクトに新しいライブラリを追加したくない場合は、素晴らしいアプローチです。しかし私の場合はFlexJsonを使う方が良いと思います。とにかく私はこの答えに留意します。ありがとう。 – huzeyfe

関連する問題