รูปแบบ Java 8 LocalDate Jackson


152

สำหรับjava.util.Dateเมื่อฉันทำ

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

จากนั้นในคำขอ JSON เมื่อฉันส่ง

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

มันได้ผล.

ฉันจะทำสิ่งนี้สำหรับฟิลด์LocalDate ของ Java 8 ได้อย่างไร ?

ฉันพยายามมี

@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>

คำตอบ:


112

ฉันไม่สามารถทำให้สิ่งนี้ทำงานได้อย่างง่ายดายโดยใช้คำอธิบายประกอบ เพื่อให้มันใช้งานได้ฉันสร้างContextResolverfor ObjectMapperจากนั้นฉันเพิ่มJSR310Module( อัปเดต: ตอนนี้เป็นJavaTimeModuleแทน ) พร้อมกับข้อแม้อีกหนึ่งข้อซึ่งจำเป็นต้องตั้งค่า write-date-as-timestamp เป็น false ดูเพิ่มเติมได้ที่เอกสารสำหรับโมดูล JSR310 นี่คือตัวอย่างของสิ่งที่ฉันใช้

การพึ่งพา

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

หมายเหตุ:ปัญหาหนึ่งที่ฉันประสบกับปัญหานี้คือ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();
        // 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;
    }  
}

ระดับทรัพยากร

@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แทน มันยังคงเป็นที่พึ่งพาเหมือนเดิม


1
สวัสดี Peeskillet วันเกิดของฟิลด์กำลังถูกสร้างเป็น "birthDate": {"year": 0, "month": "Month", "dayOfMonth": 0, "dayOfWeek": "DayOfWeek", "era": {" value ": 0}," dayOfYear ": 0," leapYear ": false," monthValue ": 0," chronology ": {" id ":" "," calendarType ":" "}} จะทำอย่างไร เป็น "birthDate" ???
JAB

ตรวจสอบว่า ContextResolver ถูกเรียก เพิ่มคำสั่งพิมพ์ในgetContextวิธีการ หากเรียกวิธีนี้ฉันไม่เห็นเหตุผลที่จะไม่ได้ผล หากไม่ได้เรียกอาจเป็นสิ่งที่ต้องแก้ไขด้วยการกำหนดค่าแอป สำหรับสิ่งนั้นฉันจะต้องดูมากกว่าสิ่งที่คุณให้ไว้ เช่นเดียวกับเวอร์ชัน Resteasy การอ้างอิงการกำหนดค่าแอปทั้ง web.xml หรือคลาสย่อยของแอปพลิเคชัน โดยทั่วไปเพียงพอที่จะทำให้เกิดปัญหา
Paul Samsotha

ContextResolver ไม่ได้ถูกเรียกว่า Peeskillet ฉันกำลังลงทะเบียนใหม่ใน web.xml เป็น <context-param> <param-name> resteasy.resources </param-name> <param-value> com.bac.ObjectMapperContextResolver </param-value> </context-param> อัปเดตคำถามสำหรับการอ้างอิงที่ฉันใช้
JAB

สแวกเกอร์ดูเหมือนจะเป็นประเด็น ฉันจะบอกว่าจะปิดการใช้งาน แต่จากคำถามนี้มีปัญหาที่ถูกยื่นออกไปโดยมีข้อขัดแย้งระหว่าง ObjectMapper ของ Swagger และพยายามใช้ของคุณเอง คุณสามารถลองและปิดใช้งานได้และใน ContextResolver ให้ตั้งค่าการกำหนดค่าทั้งหมดObjectMapperเป็นอย่างที่ผยองทำ (คุณสามารถดูลิงก์ในคำถาม) ฉันไม่รู้เพราะฉันไม่ได้ทำงานกับผยองมากนัก แต่ฉันคิดว่าผยองเป็นปัญหาหลักทำไมไม่เรียก contextresolver
Paul Samsotha

หลังจากการทดสอบเพิ่มเติมคำอธิบายประกอบจะใช้งานได้ แม้ว่าเราจะต้องใช้ Swagger ObjectMapper แต่ก็กำหนดค่าการประทับเวลาเป็นเท็จสำหรับเราแล้ว สิ่งนี้ควรได้ผล เพื่อความช่วยเหลือที่ดีขึ้นเราขอแนะนำให้คุณจัดหาMCVEที่แสดงให้เห็นถึงปัญหา
Paul Samsotha

98

@JsonSerialize และ @JsonDeserialize ทำงานได้ดีสำหรับฉัน พวกเขาไม่จำเป็นต้องนำเข้าโมดูล jsr310 เพิ่มเติม:

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

Deserializer:

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

}

Serializer:

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

2
นี่คือคำตอบที่ดีที่สุดสำหรับฉัน ขอบคุณ!
Romeo Jr Maranan

8
ชั้นเรียนเหล่านั้นรวมอยู่ในjackson-datatype-jsr310. ไม่จำเป็นต้องกำหนดเองในโครงการของคุณ
NeuroXc

1
วิธีนี้ใช้ได้ผลสำหรับฉันโดยใช้ serializers ในjackson-datatype-jsr310.
dave

2
นี่น่าจะเป็นคำตอบใหม่ที่ดีที่สุด
Doctor Parameter

2
หากคุณใช้ serializers และ deserializers ใน jackson-datatype-jsr310 ให้เพิ่ม @JsonFormat (shape = JsonFormat.Shape.STRING) ลงในฟิลด์ของคุณ หากไม่มีรูปแบบนี้ค่าจะถูกทำให้เป็นอนุกรมเป็น [ปีเดือนวัน] แม้ว่าการดีซีเรียลไลเซชั่นจะใช้งานได้
Jian Chen

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

ทำงานได้ดีสำหรับฉัน


2
new com.fasterxml.jackson.datatype.jsr310.JSR310Module()สำหรับรุ่น 2.5.4 ของ Jackson คลาส JavaTimeModule ไม่มีอยู่ในเวอร์ชันนี้
user3774109

คำตอบนี้ใช้ได้กับLocalDateTime(แจ็คสัน 2.9.5) ต้องการการพึ่งพาเพิ่มเติม 1 รายการดังนั้น build.sbt ของฉันจึงดูเหมือน:"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.9.5", "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.5"
ruhong

2
วิธีนี้ควรมีคะแนนเสียงมากกว่านี้ ง่ายและมีประสิทธิภาพ
mkasberg

ทำงานได้อย่างสมบูรณ์แบบ! ขอบคุณ.
MAD-HAX

1
สิ่งนี้ชี้ให้ฉันไปในทิศทางที่ถูกต้องขอบคุณ! ฉันจะเพิ่มว่าในสปริงบูตสิ่งที่คุณต้องทำคือเพิ่มสิ่งต่อไปนี้ใน application.properties: spring.jackson.serialization.write-date-as-timestamps = false
Joost Lambregts

50

ในแอปเว็บ Spring Boot พร้อมด้วยJacksonและJSR 310เวอร์ชัน "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
วิธีนี้ใช้ได้ผลกับ deserialization หรือไม่? หรืออนุกรมเท่านั้น? ไม่ประสบความสำเร็จกับ deserialization
rewolf

7
ฉันต้องประกาศ deserializer อย่างชัดเจน@JsonDeserialize(using= LocalDateDeserializer.class)
rewolf

1
ง่ายที่สุด!
Antonio

@JsonFormatเพียงเพื่อเปลี่ยนรูปแบบข้อมูลผลลัพธ์ stackoverflow.com/a/53251526/816759ทำงานที่สมบูรณ์แบบด้วย@JsonFormat, @JsonDeserialize,@JsonSerialize
อัลบา

1
ใน Spring Boot เมื่อคุณเพิ่มการพึ่งพา JSR310 สิ่งที่คุณต้องทำคือเพิ่มลงspring.jackson.serialization.write-dates-as-timestamps=falseในของคุณapplication.propertiesและจะจัดรูปแบบyyyy-MM-ddโดยอัตโนมัติ ไม่จำเป็นต้อง@JsonFormat
esfandia

33

วิธีแก้ปัญหาที่ง่ายที่สุด (ซึ่งรองรับ deserialization และ serialization ด้วย) คือ

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate dateOfBirth;

ในขณะที่ใช้การอ้างอิงต่อไปนี้ในโครงการของคุณ

Maven

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.9.7</version>
</dependency>
<dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jsr310</artifactId>
   <version>2.9.7</version>
</dependency>

Gradle

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

ไม่จำเป็นต้องใช้ ContextResolver, Serializer หรือ Deserializer เพิ่มเติม


เจิดจรัสไกลและง่ายที่สุด FYI สำหรับทุกคนที่มีการอ้างอิงจำนวนมากฉันต้องอัปเดตไลบรารีอื่น ๆ ที่มีคำอธิบายประกอบแจ็คสัน
brt

คำตอบนี้เป็นคำตอบที่ใกล้เคียงที่สุดที่ฉันจะแก้ไขปัญหาได้ Serialization ใช้งานได้ แต่การ deserialization ล้มเหลวเนื่องจากรูปแบบที่ฉันใช้กับ @JsonFormat ฉันคิดว่า (@JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy_HH: mm: SS")
fsakiyama

หากคุณมีการ deserialization ที่ล้มเหลวเป็นไปได้มากว่าคุณObjectMapperยังไม่ได้JavaTimeModuleลงทะเบียน หากอินสแตนซ์ ObjectMapper ของคุณมีให้จากกรอบงาน spring / MessageConverter พวกเขาใช้เวทมนตร์บางอย่างเพื่อเชื่อมต่อพวกเขา ในกรณีอื่นควรregisterModuleเปิดใช้งานLocalDateDeserializerโดยค่าเริ่มต้นสำหรับ "LocalDate" ทั้งหมดใน POJO
Dennis C

20

เนื่องจากLocalDateSerializerเปลี่ยนเป็น "[year, month, day]" (อาร์เรย์ json) แทนที่จะเป็น "year-month-day" (สตริง 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 (note: "yyyy-M-d" format will not work)
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate localDate;

ตอนนี้ฉันสามารถใช้new ObjectMapper()เพื่ออ่านและเขียนวัตถุของฉันได้โดยไม่ต้องตั้งค่าพิเศษใด ๆ


3
สิ่งหนึ่งที่ฉันต้องการเพิ่มคือการส่งวันที่"2018-12-07"แทนที่จะเป็น"2018-12-7"อย่างอื่นคุณจะได้รับข้อผิดพลาด
Kid101

1
ถูกต้องมันใช้งานได้กับyyyy-MM-ddรูปแบบyyyy-M-d( เดือนและวัน 2 หลัก) ไม่ใช่รูปแบบ(เดือนหรือวัน 1 หลัก)
Shadow Man

11
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime createdDate;

ทำงานได้ดีกว่าโซลูชันอื่น ๆ ขอบคุณ
Rouven H.

นี้ได้ผล ยังต้องการการพึ่งพาสำหรับ jackson-datatype-jsr310
W0lfw00ds

8

เพียงแค่อัปเดตคำตอบของคริสโตเฟอร์

ตั้งแต่เวอร์ชัน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


สิ่งนี้ช่วยฉันได้ ในกรณีของฉันฉันต้องเพิ่มMAPPER.registerModule(new JavaTimeModule());บรรทัด ให้ฉันจัดรูปแบบวัตถุ LocalDate เป็นรูปแบบ "2020-02-20" ฉันไม่ต้องการMAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);สายสำหรับสิ่งที่ฉันกำลังมองหา
Cuga

8

คำอธิบายประกอบต่อไปนี้ใช้ได้ผลดีสำหรับฉัน

ไม่จำเป็นต้องมีการอ้างอิงเพิ่มเติม

    @JsonProperty("created_at")
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    private LocalDateTime createdAt;

7

ง่ายและสั้นที่สุด:

@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate localDate;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime localDateTime;

ไม่จำเป็นต้องพึ่งพา Spring boot> = 2.2+


4

https://stackoverflow.com/a/53251526/1282532เป็นวิธีที่ง่ายที่สุดในการทำให้เป็นอนุกรม / deserialize คุณสมบัติ ฉันมีข้อกังวลสองประการเกี่ยวกับแนวทางนี้ - จนถึงขั้นละเมิดหลักการ DRY และการมีเพศสัมพันธ์ที่สูงระหว่าง pojo และ mapper

public class Trade {
    @JsonFormat(pattern = "yyyyMMdd")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate tradeDate;
    @JsonFormat(pattern = "yyyyMMdd")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate maturityDate;
    @JsonFormat(pattern = "yyyyMMdd")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate entryDate;
}

ในกรณีที่คุณมี POJO ที่มีช่อง LocalDate หลายช่องคุณควรกำหนดค่าตัวทำแผนที่แทน POJO สามารถทำได้ง่ายๆเพียงแค่https://stackoverflow.com/a/35062824/1282532หากคุณใช้ค่า ISO-8601 ("2019-01-31")

ในกรณีที่คุณต้องจัดการกับรูปแบบที่กำหนดเองโค้ดจะเป็นดังนี้:

ObjectMapper mapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyyMMdd")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyyMMdd")));
mapper.registerModule(javaTimeModule);

ตรรกะถูกเขียนเพียงครั้งเดียวสามารถใช้ซ้ำได้สำหรับ POJO หลายตัว


2

ในปี 2020 และ Jackson 2.10.1 ไม่จำเป็นต้องใช้รหัสพิเศษใด ๆ เพียงแค่บอกให้แจ็คสันทราบว่าคุณต้องการอะไร:

ObjectMapper objectMapper = new ObjectMapper();

// Register module that knows how to serialize java.time objects
// Provided by jackson-datatype-jsr310
objectMapper.registerModule(new JavaTimeModule());

// Ask Jackson to serialize dates as String (ISO-8601 by default)
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

สิ่งนี้ได้กล่าวไว้แล้วในคำตอบนี้ฉันกำลังเพิ่มการทดสอบหน่วยเพื่อยืนยันการทำงาน:

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Data;
import org.junit.jupiter.api.Test;

import java.time.LocalDate;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class LocalDateSerializationTest {

    @Data
    static class TestBean {
        // Accept default ISO-8601 format
        LocalDate birthDate;
        // Use custom format
        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
        LocalDate birthDateWithCustomFormat;
    }

    @Test
    void serializeDeserializeTest() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();

        // Register module that knows how to serialize java.time objects
        objectMapper.registerModule(new JavaTimeModule());

        // Ask Jackson to serialize dates as String (ISO-8601 by default)
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        // The JSON string after serialization
        String json = "{\"birthDate\":\"2000-01-02\",\"birthDateWithCustomFormat\":\"03/02/2001\"}";

        // The object after deserialization
        TestBean object = new TestBean();
        object.setBirthDate(LocalDate.of(2000, 1, 2));
        object.setBirthDateWithCustomFormat(LocalDate.of(2001, 2, 3));

        // Assert serialization
        assertEquals(json, objectMapper.writeValueAsString(object));

        // Assert deserialization
        assertEquals(object, objectMapper.readValue(json, TestBean.class));
    }
}

TestBean ใช้ Lombok เพื่อสร้างหม้อไอน้ำสำหรับถั่ว


1

ในคลาสคอนฟิกูเรชันให้กำหนดคลาสLocalDateSerializerและLocalDateDeserializerและลงทะเบียนกับObjectMapperผ่านJavaTimeModuleดังต่อไปนี้:

@Configuration
public class AppConfig
{
@Bean
    public ObjectMapper objectMapper()
    {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(Include.NON_EMPTY);
        //other mapper configs
        // Customize de-serialization


        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
        mapper.registerModule(javaTimeModule);

        return mapper;
    }

    public class LocalDateSerializer extends JsonSerializer<LocalDate> {
        @Override
        public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(value.format(Constant.DATE_TIME_FORMATTER));
        }
    }

    public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {

        @Override
        public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            return LocalDate.parse(p.getValueAsString(), Constant.DATE_TIME_FORMATTER);
        }
    }
}

0

หากคำขอของคุณมีวัตถุเช่นนี้:

{
    "year": 1900,
    "month": 1,
    "day": 20
}

จากนั้นคุณสามารถใช้:

data class DateObject(
    val day: Int,
    val month: Int,
    val year: Int
)
class LocalDateConverter : StdConverter<DateObject, LocalDate>() {
    override fun convert(value: DateObject): LocalDate {
        return value.run { LocalDate.of(year, month, day) }
    }
}

เหนือสนาม:

@JsonDeserialize(converter = LocalDateConverter::class)
val dateOfBirth: LocalDate

รหัสอยู่ใน Kotlin แต่แน่นอนว่าจะใช้ได้กับ Java เช่นกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.