Eu nunca consegui fazer isso funcionar de maneira simples usando anotações. Para obtê-lo para o trabalho, eu criei um ContextResolver
para ObjectMapper
, então eu adicionei o JSR310Module
( atualização: agora é JavaTimeModule
vez ), juntamente com mais uma ressalva, que foi a necessidade de set write-data-as-timestamp como falsa. Veja mais na documentação do módulo JSR310 . Aqui está um exemplo do que eu usei.
Dependência
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.4.0</version>
</dependency>
Nota: Um problema que enfrentei foi que a jackson-annotation
versão extraída por outra dependência, usou a versão 2.3.2, que cancelou a 2.4 exigida pelo jsr310
. O que aconteceu foi que eu recebi um NoClassDefFound ObjectIdResolver
, que é uma classe 2.4. Então, eu só precisava alinhar as versões de dependência incluídas
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();
// Now you should use JavaTimeModule instead
MAPPER.registerModule(new JSR310Module());
MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return MAPPER;
}
}
Classe de recurso
@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;
}
}
Teste
curl -v http://localhost:8080/api/person
Resultado: {"birthDate":"2015-03-01"}
curl -v -POST -H "Content-Type:application/json" -d "{\"birthDate\":\"2015-03-01\"}" http://localhost:8080/api/person
Resultado: 2015-03-01
Veja também aqui a solução JAXB.
ATUALIZAR
O JSR310Module
foi descontinuado a partir da versão 2.7 do Jackson. Em vez disso, você deve registrar o módulo JavaTimeModule
. Ainda é a mesma dependência.
getContext
método Se esse método for chamado, não vejo uma razão para isso não funcionar. Se não for chamado, pode ser algo que precise ser corrigido com a configuração do aplicativo. Para isso eu precisaria ver mais do que você forneceu. Como a versão Resteasy, dependências, a configuração do aplicativo web.xml ou a subclasse Aplicativo. Basicamente o suficiente para reproduzir o problemaObjectMapper
mesma forma que o arrogante (você pode ver um link na pergunta). Não sei, pois não trabalho muito com arrogância. Mas acho que a arrogância é o principal problema, por que o resolvedor de contexto não está sendo chamado.@JsonSerialize e @JsonDeserialize funcionaram bem para mim. Eles eliminam a necessidade de importar o módulo jsr310 adicional:
Desserializador:
Serializador:
fonte
jackson-datatype-jsr310
. Não há necessidade de defini-los manualmente em seu projeto.jackson-datatype-jsr310
.funciona bem para mim.
fonte
new com.fasterxml.jackson.datatype.jsr310.JSR310Module()
para a versão 2.5.4 do Jackson. A classe JavaTimeModule não existe nesta versão.LocalDateTime
(jackson 2.9.5). É necessária uma dependência adicional, para que o meu build.sbt se pareça com:"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.9.5", "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.5"
No aplicativo da web Spring Boot, com Jackson e JSR 310 versão "2.8.5"
Os
@JsonFormat
trabalhos:fonte
@JsonDeserialize(using= LocalDateDeserializer.class)
@JsonFormat
apenas para alterar o formato dos dados de saída. stackoverflow.com/a/53251526/816759 funciona perfeito com@JsonFormat
,@JsonDeserialize
,@JsonSerialize
spring.jackson.serialization.write-dates-as-timestamps=false
ao seuapplication.properties
e ele o formatayyyy-MM-dd
automaticamente. Não é necessário@JsonFormat
A solução mais simples (que também suporta desserialização e serialização) é
Enquanto estiver usando as seguintes dependências no seu projeto.
Maven
Gradle
Nenhuma implementação adicional de um ContextResolver, Serializer ou Deserializer é necessária.
fonte
ObjectMapper
não foiJavaTimeModule
registrado. Se sua instância do ObjectMapper for fornecida a partir da estrutura spring / MessageConverter. Eles fizeram alguma mágica para conectá-los. Em outro caso, deveregisterModule
habilitarLocalDateDeserializer
por padrão para todos os "LocalDate" no POJODesde que o
LocalDateSerializer
transforma em "[ano, mês, dia]" (uma matriz json) em vez de "ano-mês-dia" (uma sequência json) por padrão, e como eu não quero exigir nenhumaObjectMapper
configuração especial (você pode fazerLocalDateSerializer
gerar seqüências de caracteres se você desativar,SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
mas isso requer configuração adicional para o seuObjectMapper
), eu uso o seguinte:importações:
código:
E agora eu posso apenas
new ObjectMapper()
ler e escrever meus objetos sem nenhuma configuração especial.fonte
"2018-12-07"
vez disso"2018-12-7"
, você receberá um erro.yyyy-MM-dd
(2 dígitos mês e dia), não com o formatoyyyy-M-d
(1 dígito mês ou dia).Apenas uma atualização da resposta de Christopher.
Desde a versão 2.6.0
Use o JavaTimeModule em vez de JSR310Module (descontinuado).
De acordo com a documentação , o novo JavaTimeModule usa as mesmas configurações padrão para a serialização que NÃO usa IDs de fuso horário e, em vez disso, usa apenas compensações de fuso horário compatíveis com ISO-8601.
O comportamento pode ser alterado usando SerializationFeature.WRITE_DATES_WITH_ZONE_ID
fonte
MAPPER.registerModule(new JavaTimeModule());
linha. Deixe-me formatar objetos LocalDate como formato "2020-02-20". Eu não precisava daMAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
linha, pelo que estava procurandoA anotação a seguir funcionou bem para mim.
Não são necessárias dependências extras.
fonte
fonte
https://stackoverflow.com/a/53251526/1282532 é a maneira mais simples de serializar / desserializar a propriedade. Eu tenho duas preocupações com essa abordagem - até algum ponto da violação do princípio DRY e alto acoplamento entre pojo e mapper.
Caso você tenha um POJO com vários campos LocalDate, é melhor configurar o mapeador em vez do POJO. Pode ser tão simples quanto https://stackoverflow.com/a/35062824/1282532 se você estiver usando valores ISO-8601 ("2019-01-31")
Caso você precise manipular o formato personalizado, o código será assim:
A lógica é escrita apenas uma vez, pode ser reutilizada para vários POJO
fonte
Mais simples e mais curto até agora:
nenhuma dependência necessária com a inicialização Spring> = 2.2+
fonte
A partir de 2020 e Jackson 2.10.1, não há necessidade de nenhum código especial, é apenas uma questão de dizer ao Jackson o que você deseja:
Isso já foi mencionado nesta resposta , estou adicionando um teste de unidade para verificar a funcionalidade:
O TestBean usa o Lombok para gerar o padrão para o bean.
fonte
Na classe de configuração, defina LocalDateSerializer e LocalDateDeserializer e registre-as no ObjectMapper via JavaTimeModule, como abaixo:
fonte
Se sua solicitação contiver um objeto como este:
Então você pode usar:
Acima do campo:
O código está no Kotlin, mas isso também funcionaria para Java, é claro.
fonte