问题 如何将Play框架模型转换为XML和JSON?


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

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

播放XML文档 只显示使用String连接构建的XML响应,如下所示:

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

同样,JSON上的Play文档显示一次一行构建一个JSON对象。

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

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

有没有 官方游戏文档 在这个问题?


9034
2018-02-05 18:35


起源



答案:


简短回答: 杰克逊 对于 JSON 和 JAXB 对于 XML

 本身不提供任何文件 编组 模型,但它确实附带 第三方图书馆 那可以做到这一点。


JSON:

该模型:

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

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

使用杰克逊的马歇尔将其转换为JSON ObjectMapper.writeValueAsString() 方法。

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 注释到 属性。这告诉JAXB从中序列化 的getter / setter方法 而不是来自 基础领域

@XmlAccessorType(XmlAccessType.PROPERTY)

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

@XmlRootElement(name = "UserRoot")

要省略一个字段,我们必须添加 @XmlTransient 对getter的注释。由于源代码中没有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类执行 编组 和 的JAXBContext

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的文档 和 在JSON上播放文档 确实提供了一些有关使用json / xml的信息,但似乎没有任何Play Docs描述如何操作 编组。为此,我们必须看一看 第三方图书馆 和文件。


11
2018-02-11 10:17





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

对于 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的模板会将其转义,因此不会 <>" 它会用 &lt;&gt&quot; 在XML节点内:

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

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

你还可以使用部分模板 - 标签 为了确保这个单项在两者中的格式完全相同: users/1.xml 和 users/all.xml


2
2018-02-05 21:15



谢谢biesior。杰克逊文档一次构建一个json字段。我正在寻找的是一种在单个语句中自动将模型转换为json的方法,使用java类名和java字段名作为相应的json标识符。杰克逊有可能吗?你知道描述这个的任何文档吗? XML模板方法的问题在于它并不总是返回格式良好的XML。例如,如果数据包含任何特殊字符,如<或>或“,这些将在运行时破坏xml。保证格式良好的生成器是必不可少的。谢谢 - KevSheedy
我不知道格式化XML,无论如何仍然认为可以使用模板,检查我的编辑。 - biesior
你的评论在这里救了我,我认为Play不支持创建JSON数组的简单方法是荒谬的!为什么它不支持play.libs.Json.newObject()的put(ArrayList <>())???感谢您的回答! - ossys
怎么样 yourObjectNode.put("items", Json.toJson(yourArray)) ? - biesior


答案:


简短回答: 杰克逊 对于 JSON 和 JAXB 对于 XML

 本身不提供任何文件 编组 模型,但它确实附带 第三方图书馆 那可以做到这一点。


JSON:

该模型:

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

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

使用杰克逊的马歇尔将其转换为JSON ObjectMapper.writeValueAsString() 方法。

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 注释到 属性。这告诉JAXB从中序列化 的getter / setter方法 而不是来自 基础领域

@XmlAccessorType(XmlAccessType.PROPERTY)

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

@XmlRootElement(name = "UserRoot")

要省略一个字段,我们必须添加 @XmlTransient 对getter的注释。由于源代码中没有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类执行 编组 和 的JAXBContext

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的文档 和 在JSON上播放文档 确实提供了一些有关使用json / xml的信息,但似乎没有任何Play Docs描述如何操作 编组。为此,我们必须看一看 第三方图书馆 和文件。


11
2018-02-11 10:17





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

对于 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的模板会将其转义,因此不会 <>" 它会用 &lt;&gt&quot; 在XML节点内:

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

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

你还可以使用部分模板 - 标签 为了确保这个单项在两者中的格式完全相同: users/1.xml 和 users/all.xml


2
2018-02-05 21:15



谢谢biesior。杰克逊文档一次构建一个json字段。我正在寻找的是一种在单个语句中自动将模型转换为json的方法,使用java类名和java字段名作为相应的json标识符。杰克逊有可能吗?你知道描述这个的任何文档吗? XML模板方法的问题在于它并不总是返回格式良好的XML。例如,如果数据包含任何特殊字符,如<或>或“,这些将在运行时破坏xml。保证格式良好的生成器是必不可少的。谢谢 - KevSheedy
我不知道格式化XML,无论如何仍然认为可以使用模板,检查我的编辑。 - biesior
你的评论在这里救了我,我认为Play不支持创建JSON数组的简单方法是荒谬的!为什么它不支持play.libs.Json.newObject()的put(ArrayList <>())???感谢您的回答! - ossys
怎么样 yourObjectNode.put("items", Json.toJson(yourArray)) ? - biesior


有一种更好的JSON转换方式。

User user = new User("...");
String jsonString = Ebean.json().toJson(user);

1
2017-07-26 05:46