如何在 Play Framework JSON Rest 上使用 java.time.LocalDate?
How to use java.time.LocalDate on a Play Framework JSON Rest?
我正在尝试使 Play 序列化和反序列化 java 8 LocalDate。
在 Play 2.4 上,据说开箱即用:
Play 2.4 now requires JDK 8. Due to this, Play can, out of the box, provide support for Java 8 data types. For example, Play’s JSON APIs now support Java 8 temporal types including Instance, LocalDateTime and LocalDate.
但我无法让它工作。
这是我的资料:
我正在使用带有 PlayJava 和 PlayEbean 插件的 Play 2.4.3
型号
@Entity
public class Person extends Model {
@Id
public Long id;
public String name;
public LocalDate dayOfBirth;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
public LocalDate anotherDate;
@Formats.DateTime(pattern = "dd/MM/yyyy")
public LocalDate andAnotherOne;
public static Model.Finder<Long, Person> find = new Model.Finder<Long, Person>(Person.class);
}
控制器
public class PersonController extends Controller {
public Result create() {
Person person = Json.fromJson(request().body().asJson(), Person.class);
person.save();
return ok(Json.toJson(person));
}
public Result all() {
return ok(Json.toJson(Person.find.all()));
}
}
路线
POST /person @controllers.PersonController.create()
GET /person @controllers.PersonController.all()
我使用 chrome REST 应用对其进行了测试,并在三种形式中出现错误:
{"name":"Fred","dayOfBirth":"2015-09-30"}
{"name":"Fred","anotherDate":"30/09/2015"}
{"name":"Fred","andAnotherOne":"30/09/2015"}
错误
java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDate] from String value ('2015-09-30'); no single-String constructor/factory method
at [Source: N/A; line: -1, column: -1] (through reference chain: models.Person["dayOfBirth"])
我错过了什么?
我发现了问题,Play 正在注入一个自定义的 ObjectMapper,我认为它没有注册 jackson 的 Jdk8Module 和 JSR310Module。
我开了一个issue
我找到的解决方法是在 Global.java
上设置您自己的 ObjectMapper
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
import play.Application;
import play.GlobalSettings;
import play.libs.Json;
/**
* Criado por ferrao em 01/10/2015.
*/
public class Global extends GlobalSettings {
public void onStart(Application app) {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JSR310Module());
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Json.setObjectMapper(mapper);
}
}
我从 play.libs.Json 来源复制的 mapper.configure 部分
我正在尝试使 Play 序列化和反序列化 java 8 LocalDate。
在 Play 2.4 上,据说开箱即用:
Play 2.4 now requires JDK 8. Due to this, Play can, out of the box, provide support for Java 8 data types. For example, Play’s JSON APIs now support Java 8 temporal types including Instance, LocalDateTime and LocalDate.
但我无法让它工作。
这是我的资料: 我正在使用带有 PlayJava 和 PlayEbean 插件的 Play 2.4.3
型号
@Entity
public class Person extends Model {
@Id
public Long id;
public String name;
public LocalDate dayOfBirth;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
public LocalDate anotherDate;
@Formats.DateTime(pattern = "dd/MM/yyyy")
public LocalDate andAnotherOne;
public static Model.Finder<Long, Person> find = new Model.Finder<Long, Person>(Person.class);
}
控制器
public class PersonController extends Controller {
public Result create() {
Person person = Json.fromJson(request().body().asJson(), Person.class);
person.save();
return ok(Json.toJson(person));
}
public Result all() {
return ok(Json.toJson(Person.find.all()));
}
}
路线
POST /person @controllers.PersonController.create()
GET /person @controllers.PersonController.all()
我使用 chrome REST 应用对其进行了测试,并在三种形式中出现错误:
{"name":"Fred","dayOfBirth":"2015-09-30"}
{"name":"Fred","anotherDate":"30/09/2015"}
{"name":"Fred","andAnotherOne":"30/09/2015"}
错误
java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDate] from String value ('2015-09-30'); no single-String constructor/factory method
at [Source: N/A; line: -1, column: -1] (through reference chain: models.Person["dayOfBirth"])
我错过了什么?
我发现了问题,Play 正在注入一个自定义的 ObjectMapper,我认为它没有注册 jackson 的 Jdk8Module 和 JSR310Module。
我开了一个issue
我找到的解决方法是在 Global.java
上设置您自己的 ObjectMapperimport com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
import play.Application;
import play.GlobalSettings;
import play.libs.Json;
/**
* Criado por ferrao em 01/10/2015.
*/
public class Global extends GlobalSettings {
public void onStart(Application app) {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JSR310Module());
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Json.setObjectMapper(mapper);
}
}
我从 play.libs.Json 来源复制的 mapper.configure 部分