§处理和提供 JSON
在 Java 中,Play 使用 Jackson JSON 库将对象转换为 JSON 以及从 JSON 转换对象。Play 的操作使用 JsonNode
类型,并且框架在 play.libs.Json
API 中提供了用于转换的实用程序方法。
§将 Java 对象映射到 JSON
Jackson 允许您通过查看字段名称、getter 和 setter 来轻松地将 Java 对象转换为 JSON。例如,我们将使用以下简单的 Java 对象
// Note: can use getters/setters as well; here we just use public fields directly.
// if using getters/setters, you can keep the fields `protected` or `private`
public static class Person {
public String firstName;
public String lastName;
public int age;
}
我们可以解析对象的 JSON 表示并创建一个新的 Person
Person person = new Person();
person.firstName = "Foo";
person.lastName = "Bar";
person.age = 30;
JsonNode personJson = Json.toJson(person); // {"firstName": "Foo", "lastName": "Bar", "age": 30}
类似地,我们可以将 Person
对象写入 JsonNode
// parse the JSON as a JsonNode
JsonNode json = Json.parse("{\"firstName\":\"Foo\", \"lastName\":\"Bar\", \"age\":13}");
// read the JsonNode as a Person
Person person = Json.fromJson(json, Person.class);
§处理 JSON 请求
JSON 请求是使用有效 JSON 负载作为请求主体进行的 HTTP 请求。其 Content-Type
标头必须指定 text/json
或 application/json
MIME 类型。
默认情况下,操作使用 任何内容 主体解析器,您可以使用它以 JSON(实际上是 Jackson JsonNode
)的形式检索主体
public Result sayHello(Http.Request request) {
JsonNode json = request.body().asJson();
if (json == null) {
return badRequest("Expecting Json data");
} else {
String name = json.findPath("name").textValue();
if (name == null) {
return badRequest("Missing parameter [name]");
} else {
return ok("Hello " + name);
}
}
}
public Result sayHello(Http.Request request) {
Optional<Person> person = request.body().parseJson(Person.class);
return person.map(p -> ok("Hello, " + p.firstName)).orElse(badRequest("Expecting Json data"));
}
当然,最好(也更简单)指定我们自己的 BodyParser
来要求 Play 直接将内容主体解析为 JSON
@BodyParser.Of(BodyParser.Json.class)
public Result sayHello(Http.Request request) {
JsonNode json = request.body().asJson();
String name = json.findPath("name").textValue();
if (name == null) {
return badRequest("Missing parameter [name]");
} else {
return ok("Hello " + name);
}
}
注意: 这样,对于 Content-type 设置为 application/json 的非 JSON 请求,将自动返回 400 HTTP 响应。
您可以从命令行使用 curl
进行测试
curl
--header "Content-type: application/json"
--request POST
--data '{"name": "Guillaume"}'
https://127.0.0.1:9000/sayHello
它将回复
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 15
Hello Guillaume
§提供 JSON 响应
在我们之前的示例中,我们处理了 JSON 请求,但回复了 text/plain
响应。让我们将其更改为发送有效的 JSON HTTP 响应
public Result sayHello() {
ObjectNode result = Json.newObject();
result.put("exampleField1", "foobar");
result.put("exampleField2", "Hello world!");
return ok(result);
}
现在它将回复
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"exampleField1":"foobar","exampleField2":"Hello world!"}
您还可以返回 Java 对象,并让 Jackson 库将其自动序列化为 JSON
public Result getPeople() {
List<Person> people = personDao.findAll();
return ok(Json.toJson(people));
}
如果您已经拥有要返回的 JSON String
,您也可以这样做
public Result sayHello() {
String jsonString = "{\"exampleField1\": \"foobar\"}";
return ok(jsonString).as(play.mvc.Http.MimeTypes.JSON);
}
§高级用法
有两种可能的方法可以为您的应用程序自定义 ObjectMapper
。
§application.conf
中的配置
由于 Play 使用 Pekko Jackson 序列化支持,您可以根据应用程序需求配置 ObjectMapper
。有关 jackson-databind 特性的文档 说明了如何进一步自定义 JSON 转换过程,包括 Mapper、序列化 和 反序列化 功能。
如果您想使用 Play 的 Json
API(toJson
/fromJson
)与自定义的 ObjectMapper
,您需要在 application.conf
中添加自定义配置。例如,如果您想添加一个新的 Joda 类型模块
pekko.serialization.jackson.play.jackson-modules += "com.fasterxml.jackson.datatype.joda.JodaModule"
或者添加设置序列化配置
pekko.serialization.jackson.play.serialization-features.WRITE_NUMBERS_AS_STRINGS=true
§ObjectMapper
的自定义绑定
如果您仍然想完全接管 ObjectMapper
的创建,可以通过覆盖其绑定配置来实现。您首先需要在 application.conf
中禁用默认的 ObjectMapper
模块
play.modules.disabled += "play.core.ObjectMapperModule"
然后您可以为您的 ObjectMapper
创建一个提供者
public class JavaJsonCustomObjectMapper implements Provider<ObjectMapper> {
@Override
public ObjectMapper get() {
ObjectMapper mapper =
new ObjectMapper()
// enable features and customize the object mapper here ...
.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// Needs to set to Json helper
Json.setObjectMapper(mapper);
return mapper;
}
}
并通过 Guice 将其绑定为一个急切的单例,以便 ObjectMapper
将被设置到 Json
帮助器中
public class JavaJsonCustomObjectMapperModule extends AbstractModule {
@Override
protected void configure() {
bind(ObjectMapper.class).toProvider(JavaJsonCustomObjectMapper.class).asEagerSingleton();
}
}
之后启用模块
play.modules.enabled += "path.to.JavaJsonCustomObjectMapperModule"
下一步:使用 XML
发现此文档中的错误?此页面的源代码可以在 此处 找到。在阅读了 文档指南 之后,请随时贡献一个拉取请求。有疑问或建议要分享?前往 我们的社区论坛 与社区开始对话。