2012-03-09 85 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