我正在使用Play Framework 1.2.4和Java并使用JPA来保存我的数据库对象。我有几个Model类要呈现为JSON。但问题是我想在渲染为JSON之前自定义这些JSON响应并简化对象。
例如,假设我有一个名为ComplexClass的对象,并且具有属性id,name,property1,...,propertyN。在JSON响应中,我想只渲染id和name字段。
这样做最优雅的方式是什么?编写自定义绑定对象或是否有简单的JSON映射,例如使用模板?
答案 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())
。
编辑:列表/集合的额外示例
好的,当你开始序列化列表时,你可能会得到一些意想不到的结果。这是因为评估顺序很重要。第一个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。