Play Framework:渲染自定义JSON对象

huz*_*yfe 3 java json playframework

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

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

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

dig*_*nie 8

Play Framework 1.2.4直接依赖于gson库,因此您可以使用它来呈现您的JSON字符串.您所要做的就是使用gson的@Expose注释.因此,在您的示例中,您将在JSON字符串中标记所需的字段,如下所示:

public class ComplexClass {

    @Expose
    public Long id;

    @Expose
    public String name;

    ...
}
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器中,你会这样做:

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);
}
Run Code Online (Sandbox Code Playgroud)

见文档这里.

如果ComplexClass实际上是a 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;
    }
Run Code Online (Sandbox Code Playgroud)

然后控制器会略微改变,看起来像这样:

    GsonBuilder builder = new GsonBuilder();
    ComplexClassExclusionStrategy strategy = new ComplexClassExclusionStrategy();
    builder.setExclusionStrategies(strategy);
    Gson gson = builder.create();
    String json = gson.toJson(complex);
    renderJson(json);
Run Code Online (Sandbox Code Playgroud)


maa*_*cls 6

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

查看这篇文章,了解在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);
  }
Run Code Online (Sandbox Code Playgroud)

}

您可以将它添加到您的dependencies.yml中,如下所示:

require:
    - play
    - net.sf.flexjson -> flexjson 2.1
Run Code Online (Sandbox Code Playgroud)

我通常做的是为实现toJSONString()方法的模型编写一个接口,以便我可以renderJSON(someModel.toJSONString())在控制器中调用.

链接到官方网站

编辑:列表/集合的额外示例

好的,当你开始序列化列表时,你可能会得到一些意想不到的结果.这是因为评估顺序很重要.第一个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);
Run Code Online (Sandbox Code Playgroud)

*顺便说一句,这是一个通配符.这篇文档完美地解释了它:
一个排除*.class符合任何路径深度.因此,如果flexjson使用"foo.bar.class"路径序列化字段,则*in *.class将匹配foo.bar.