12

Play 框架是否有将 Play 模型转换为 XML/JSON的本推荐方式?类似于 JAXB 或 Jackson 的东西。

有些人推荐模板方法,但这非常冗长,并且不能保证格式正确的 XML/JSON。

XML 上的播放文档仅显示使用字符串连接构建的 XML 响应,如下所示:

return ok("<message \"status\"=\"OK\">Hello " + name + "</message>");

类似地,JSON 上的播放文档显示了一个 JSON 对象一次构建一行。

ObjectNode result = Json.newObject();
result.put("status", "OK");
result.put("message", "Hello " + name);

是否有使用 Play 将模型序列化为 XML/JSON的标准方法?

有没有关于这个主题的官方游戏文档?

4

3 回答 3

12

简短回答:Jackson for JSONJAXB for XML

Play本身不提供任何关于编组模型的文档,但它确实附带了可以完成这项工作的3rd 方库。


JSON:

该模型:

public class User extends Model {
    public String username;
    public Long   age; 

    @JsonIgnore
    public String password; // field won't be marshalled
}

使用杰克逊的ObjectMapper.writeValueAsString()方法将其编组为 JSON。

import org.codehaus.jackson.map.ObjectMapper;
//
ObjectMapper mapper     = new ObjectMapper();
String       jsonString = mapper.writeValueAsString(country);

JSON输出:

{
    "username" : "John Smith",
    "age"      : "25"
}

XML:

必须小心,因为 Play 如何在后台为其模型生成 getter 和 setter 。您不会在代码中看到 getter 和 setter,但它们在运行时存在。

在模型上,将XmlAccessorType注释设置为PROPERTY很重要。这告诉 JAXB 从getter/setter序列化,而不是从底层字段序列化。

@XmlAccessorType(XmlAccessType.PROPERTY)

我们还必须添加一个@XmlRootElement注释,它指定根 XML 节点的名称:

@XmlRootElement(name = "UserRoot")

要省略字段,我们必须将@XmlTransient注释添加到 getter。由于源代码中没有 getter,我们必须为要省略的每个字段添加一个。

@XmlAccessorType(XmlAccessType.PROPERTY)
public class User extends Model {
    public String username;
    public Long   age;

    @JsonIgnore
    public String password;


    @XmlTransient // This means ignore this property
    public String getPassword() {
        return this.password;
    }
}

编组由 JAXB 类MarshallerJAXBContext执行

JAXBContext context    = JAXBContext.newInstance(User.class);
Marshaller  marshaller = context.createMarshaller();

// Use linefeeds and indentation in the outputted XML
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

marshaller.marshal(user, System.out);

输出:

<UserRoot>
    <name>John Smith</name>
    <age>25</age>
</UserRoot>

概括:

XML 上Play 文档和 JSON上的Play 文档确实提供了一些有关使用 json/xml 的信息,但似乎没有任何 Play Docs 描述如何进行Marshalling。为此,我们必须查看第 3 方库和文档。

于 2013-02-11T10:17:29.330 回答
2

对于 JSON,我建议使用 ... org.codehaus.jackson,因为它play.libs.JsonPlay 2/x @see: Json Doc中可用

For XML- 模板方法足够公平,因为您可以使用视图呈现适当的 XML。

编辑:

Json 和 Ebean

遗憾的是,Ebean 在将其对象序列化为 JSON 时存在问题,因此我总是使用专用的内部类(在目标模型中,它只包含应该在 Json 中发送的字段),即User模型:

public static class ForJson {
    public Long id;
    public String name;
    public String email;

    public ForJson(User user) {
        this.id = user.id;
        this.name = user.name;
        this.email=user.email;
    }
}

路线:

GET     /users/all.json            controllers.Application.listUsersJson
GET     /users/all-details.json    controllers.Application.listUsersJsonWithDetails
GET     /users/:id.json            controllers.Application.singleUserJson(id: Long)

行动:

public static Result listUsersJson() {
    List<User.ForJson> usersToJson = new ArrayList<>();
    for (User user : User.find.all()) {
        usersToJson.add(new User.ForJson(user));
    }
    return ok(Json.toJson(usersToJson));
}

public static Result singleUserJson(Long id) {
    User.ForJson userForJson = new User.ForJson(User.find.byId(id));
    return ok(Json.toJson(userForJson));
}

public static Result listUsersJsonWithDetails() {
    Map<String, Object> details = new LinkedHashMap<>();

    List<User.ForJson> usersToJson = new ArrayList<>();
    for (User user : User.find.all()) {
        usersToJson.add(new User.ForJson(user));
    }

    details.put("date", new Date());
    details.put("count", usersToJson.size());
    details.put("users", usersToJson);

    return ok(Json.toJson(details));
}

是的,我知道这可能是冗余编码,但我至少总是有正确的 JSON 输出,而且我不需要在每个操作中逐行创建 JSON。.

XML:

HTML 字符不会破坏正确的 XML 渲染,因为默认情况下 Play 的模板会转义它们,因此它将在XML 节点内使用,代替<, :>"&lt;&gt&quot;

<sample>Say &quot;ellou&quot;<sample>

检查模板文档中的转义段落(页面底部)。

更重要的是,您可以使用部分模板 -标记来确保单个项目在两者中的格式完全相同:users/1.xmlusers/all.xml

于 2013-02-05T21:15:29.620 回答
1

JSON转换有更好的方法。

User user = new User("...");
String jsonString = Ebean.json().toJson(user);
于 2016-07-26T05:46:42.070 回答