Play Framework:渲染自定义JSON对象

时间:2012-03-09 17:38:04

标签: java json playframework

我正在使用Play Framework 1.2.4和Java并使用JPA来保存我的数据库对象。我有几个Model类要呈现为JSON。但问题是我想在渲染为JSON之前自定义这些JSON响应并简化对象。

例如,假设我有一个名为ComplexClass的对象,并且具有属性id,name,property1,...,propertyN。在JSON响应中,我想只渲染id和name字段。

这样做最优雅的方式是什么?编写自定义绑定对象或是否有简单的JSON映射,例如使用模板?

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:6)

使用FlexJSON,非常简单。它允许您创建可以包含/排除所需字段的JSONSerializers。

查看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

我通常做的是为实现toJSONString()方法的模型编写接口,以便我可以在控制器中调用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。