Как использовать java.time.LocalDate в Play Framework JSON Rest?

Я безуспешно пытаюсь заставить Play сериализовать и десериализовать java 8 LocalDate.

Говорят, что в Play 2.4 это работает из коробки:

Для Play 2.4 теперь требуется JDK 8. Благодаря этому Play может «из коробки» обеспечивать поддержку типов данных Java 8. Например, JSON API от Play теперь поддерживают временные типы Java 8, включая Instance, LocalDateTime и LocalDate.

Но я не могу заставить его работать.

Вот что у меня есть: я использую Play 2.4.3 с плагинами PlayJava и PlayEbean.

Модель

@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"])

Что мне не хватает?

обновление: пример приложения: https://github.com/fredferrao/LocalDateJSONTest


person Fred    schedule 30.09.2015    source источник


Ответы (1)


Я обнаружил проблему: Play вводит пользовательский ObjectMapper, и я думаю, что он не регистрирует Jdk8Module и JSR310Module jackson.

Я открыл проблему

Обходной путь, который я нашел, - установить свой собственный ObjectMapper на Global.java

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);
    }
}

Часть mapper.configure, которую я скопировал из источника play.libs.Json

person Fred    schedule 01.10.2015
comment
Я думаю, что у меня такая же проблема. Я также использую play 2.4 и начал свой проект практически с нуля. По умолчанию кажется, что они больше не имеют/не используют глобальный объект. По крайней мере, это обескураживает. playframework.com/documentation/2.4.x/GlobalSettings Есть идеи, как настроить ObjectMapper без него? Или мне все-таки нужно теперь включить объект GlobalSettings, чтобы обойти эту ошибку? - person svaens; 30.12.2015
comment
На самом деле, я был неправ. Это другая ошибка: Вызвано: java.lang.IllegalStateException: Форма привязки ошибок: {dateOfBirth:[Invalid value]} в play.data.Form.get(Form.java:592) ~[play-java_2 .11-2.4.4.jar:2.4.4] - person svaens; 30.12.2015
comment
на самом деле, помимо моей собственной проблемы, мне в конце концов пришлось решить проблему json так, как это сделали вы. Благодарю вас! - person svaens; 31.12.2015
comment
Как исправить проблему сериализации, когда при преобразовании в JSON LocalDate форматируется как массив [2016, 8, 11], я бы хотел, чтобы он был в формате ISO 8061, например 2016-08-11. - person Jaanus; 26.08.2016
comment
@Jaanus просто добавьте аннотацию @JsonFormat(shape = STRING) в поле LocalDate. - person Cepr0; 06.12.2019