§處理和提供 JSON
在 Java 中,Play 使用 Jackson 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 要求是一種 HTTP 要求,使用有效的 JSON 負載作為要求主體。其 `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);
}
}
注意:這樣一來,對於內容類型設定為 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 字串
,想回傳,也可以這麼做
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
在這個文件找到錯誤了嗎?此頁面的原始程式碼可以在 這裡 找到。在閱讀 文件指南 後,請隨時提交 pull request。有問題或建議要分享嗎?前往 我們的社群論壇 與社群展開對話。