2012-03-09 133 views
3

我正在使用Play Framework 1.2.4與Java並使用JPA來堅持我的數據庫對象。我有幾個模型類被渲染爲JSON。但問題是我想定製這些JSON響應,並在渲染爲JSON之前簡化對象。例如,假設我有一個名爲ComplexClass並具有屬性id,name,property1,...,propertyN的對象。在JSON響應中,我只想渲染id和名稱字段。Play Framework:呈現自定義JSON對象

這樣做的最優雅的方式是什麼?編寫自定義綁定對象還是有簡單的JSON映射,如使用模板?

回答

6

使用FlexJSON,這很容易。它允許您創建可以包含/排除所需字段的JSONSerializer。

查看this article的一些使用Play的例子!框架。
這裏有一個簡單的例子:

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); 
    } 

}

你可以把它添加到您的dependencies.yml像這樣:

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

我最常做的是寫模式,實現的接口我可以在控制器中調用renderJSON(someModel.toJSONString())

Link to official website

編輯:對列表/收藏

好吧,當你開始序列化列表中,您可能會得到一些意想不到的結果額外的例子。這是因爲評估順序很重要。第一個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 2012-03-12 09:13:55

+0

順便說一句,(如果可能的話)你能提供一些關於你的接口細節的細節,這樣我也可以用這種方式在控制器中使用,因爲我也需要序列化對象列表。 – huzeyfe 2012-03-12 12:24:49

+1

更新了一個列表示例:) – maartencls 2012-03-13 12:58:56

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 2012-03-12 09:17:09