Формат Java 8 LocalDate Jackson

на java.утиль.Дата когда я делаю

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")  
  private Date dateOfBirth;

затем в запросе JSON, когда я отправляю

{ {"dateOfBirth":"01/01/2000"} }  

это работает.

как я должен это сделать для Java 8's LocalDate поле??

Я пыталась

@JsonDeserialize(using = LocalDateDeserializer.class)  
@JsonSerialize(using = LocalDateSerializer.class)  
private LocalDate dateOfBirth;  

это не сработало.

может кто-нибудь, пожалуйста, дайте мне знать, как правильно это сделать..

Ниже приведены зависимости

<dependency>
         <groupId>org.jboss.resteasy</groupId>
         <artifactId>jaxrs-api</artifactId>
         <version>3.0.9.Final</version>
      </dependency>
      <dependency>
         <groupId>com.fasterxml.jackson.jaxrs</groupId>
         <artifactId>jackson-jaxrs-json-provider</artifactId>
         <version>2.4.2</version>
      </dependency>
      <dependency>
         <groupId>com.wordnik</groupId>
         <artifactId>swagger-annotations</artifactId>
         <version>1.3.10</version>
      </dependency>
      <dependency>

6 ответов


Я никогда не мог заставить это работать просто, используя аннотации. Чтобы заставить его работать, я создал ContextResolver на ObjectMapper, затем я добавил JSR310Module, а также еще одно предостережение, которое заключалось в необходимости установить метку даты записи как времени на false. Подробнее в документация для модуля JSR310. Вот пример того, что я использовал.

зависимость

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.4.0</version>
</dependency>

Примечание: одна проблема, с которой я столкнулся, заключается в том, что the jackson-annotation версия, вытащенная другой зависимостью, использовала версию 2.3.2, которая отменила 2.4, требуемую jsr310. Случилось так, что я получил NoClassDefFound за ObjectIdResolver, который является классом 2.4. Так я только для версий зависимостей

ContextResolver

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper MAPPER;

    public ObjectMapperContextResolver() {
        MAPPER = new ObjectMapper();
        MAPPER.registerModule(new JSR310Module());
        MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return MAPPER;
    }  
}

класс ресурсов

@Path("person")
public class LocalDateResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getPerson() {
        Person person = new Person();
        person.birthDate = LocalDate.now();
        return Response.ok(person).build();
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createPerson(Person person) {
        return Response.ok(
                DateTimeFormatter.ISO_DATE.format(person.birthDate)).build();
    }

    public static class Person {
        public LocalDate birthDate;
    }
}

тест

curl -v http://localhost:8080/api/person
результат: {"birthDate":"2015-03-01"}

curl -v -POST -H "Content-Type:application/json" -d "{\"birthDate\":\"2015-03-01\"}" http://localhost:8080/api/person
результат: 2015-03-01


см. также здесь для решения JAXB.

обновление

на JSR310Module считается устаревшим с версии 2.7 Джексона. Вместо этого, вы должны зарегистрировать модуль JavaTimeModule. Это все та же зависимость.


@JsonSerialize и @JsonDeserialize отлично работали для меня. Они устраняют необходимость импорта дополнительного модуля jsr310:

@JsonDeserialize(using = LocalDateDeserializer.class)  
@JsonSerialize(using = LocalDateSerializer.class)  
private LocalDate dateOfBirth;

десериализатор:

public class LocalDateDeserializer extends StdDeserializer<LocalDate> {

    private static final long serialVersionUID = 1L;

    protected LocalDateDeserializer() {
        super(LocalDate.class);
    }


    @Override
    public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        return LocalDate.parse(jp.readValueAs(String.class));
    }

}

сериализатор:

public class LocalDateSerializer extends StdSerializer<LocalDate> {

    private static final long serialVersionUID = 1L;

    public LocalDateSerializer(){
        super(LocalDate.class);
    }

    @Override
    public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider sp) throws IOException, JsonProcessingException {
        gen.writeString(value.format(DateTimeFormatter.ISO_LOCAL_DATE));
    }
}

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

отлично работает для меня.


весной загрузки веб-приложения, с "Джексон" и "jsr310" версии "2.8.5"

compile "com.fasterxml.jackson.core:jackson-databind:2.8.5"
runtime "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.5"

"@JsonFormat " работает:

import com.fasterxml.jackson.annotation.JsonFormat;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate birthDate;

просто обновление ответа Кристофера.

начиная с версии 2.6.0

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.9.0</version>
</dependency>

использовать JavaTimeModule вместо JSR310Module (рекомендуется).

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper MAPPER;

    public ObjectMapperContextResolver() {
        MAPPER = new ObjectMapper();
        MAPPER.registerModule(new JavaTimeModule());
        MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return MAPPER;
    }  
}

по словам документация, новый JavaTimeModule использует те же стандартные настройки по умолчанию для сериализации, которая не использует идентификаторы часового пояса, и вместо этого использует только ISO-8601 совместимые смещения часового пояса.

поведение может быть изменено с помощью SerializationFeature.WRITE_DATES_WITH_ZONE_ID


С LocalDateSerializer превращает его в " [год, месяц, день]" (массив json), а не "год-месяц-день" (строка json) по умолчанию, и поскольку я не хочу требовать каких-либо специальных ObjectMapper настройка (можно сделать LocalDateSerializer генерировать строки, если отключить SerializationFeature.WRITE_DATES_AS_TIMESTAMPS но для этого требуется дополнительная настройка вашего ObjectMapper), Я использую следующие:

импорт:

import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;

код:

// generates "yyyy-MM-dd" output
@JsonSerialize(using = ToStringSerializer.class)
// handles "yyyy-MM-dd" input just fine
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate localDate;

и теперь я могу просто использовать new ObjectMapper() читать и писать мои объекты без каких-либо специальных установка.