itsource

JSON Jackson에 대한 날짜 형식 매핑

mycopycode 2022. 12. 4. 22:35
반응형

JSON Jackson에 대한 날짜 형식 매핑

API에서 제공되는 Date 포맷은 다음과 같습니다.

"start_time": "2015-10-1 3:00 PM GMT+1:00"

YYY-DD-MM HH는 무엇입니까?MM am/pm GMT 타임스탬프이 값을 POJO의 날짜 변수에 매핑합니다.분명히 변환 오류를 나타내고 있습니다.

다음 두 가지를 알고 싶습니다.

  1. 잭슨과의 변환에 필요한 포맷은 무엇입니까?이 경우 Date가 적합한 필드 유형입니까?
  2. 일반적으로 변수가 잭슨에 의해 오브젝트 멤버에게 매핑되기 전에 처리할 수 있는 방법이 있습니까?예를 들어 형식 변경, 계산 등.

Jackson v2.0 이후 오브젝트 멤버에게 직접 @JsonFormat 주석을 사용할 수 있습니다.

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm a z")
private Date date;

잭슨과의 변환에 필요한 포맷은 무엇입니까?이 경우 Date가 적합한 필드 유형입니까?

Date이 경우 적합한 필드 유형입니다.은 JSON을 할 수 .ObjectMapper.setDateFormat:

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
myObjectMapper.setDateFormat(df);

일반적으로 변수가 잭슨에 의해 오브젝트 멤버에게 매핑되기 전에 처리할 수 있는 방법이 있습니까?예를 들어 형식 변경, 계산 등.

네의 몇 옵션이 . 이데올로기 때문에JsonDeserializer)JsonDeserializer<Date>시작이 좋다.

물론 serialization과 deserialization이라고 하는 자동화된 방법이 있으며 pb2q에서 설명한 바와 같이 특정 주석(@JsonSerialize,@JsonDeserialize)으로 정의할 수도 있습니다.

두 java.util을 모두 사용할 수 있습니다.날짜 및 java.util.달력... 그리고 아마 Joda Time도 있을 거예요.

@JsonFormat 주석이 역직렬화(시리얼라이제이션이 완벽하게 작동) 원하는 대로 작동하지 않았습니다(타임존을 다른 값으로 조정했습니다).

@JsonFormat(locale = "hu", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "CET")

@JsonFormat(locale = "hu", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "Europe/Budapest")

예측 결과를 원하는 경우 @JsonFormat 주석 대신 커스텀시리얼라이저와 커스텀디시리얼라이저를 사용해야 합니다.http://www.baeldung.com/jackson-serialize-dates에서 정말 좋은 튜토리얼과 솔루션을 찾았습니다.

날짜 필드에는 예가 있지만 캘린더 필드에는 필요하기 때문에 구현은 다음과 같습니다.

시리얼라이저 클래스:

public class CustomCalendarSerializer extends JsonSerializer<Calendar> {

    public static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    public static final Locale LOCALE_HUNGARIAN = new Locale("hu", "HU");
    public static final TimeZone LOCAL_TIME_ZONE = TimeZone.getTimeZone("Europe/Budapest");

    @Override
    public void serialize(Calendar value, JsonGenerator gen, SerializerProvider arg2)
            throws IOException, JsonProcessingException {
        if (value == null) {
            gen.writeNull();
        } else {
            gen.writeString(FORMATTER.format(value.getTime()));
        }
    }
}

디시리얼라이저 클래스:

public class CustomCalendarDeserializer extends JsonDeserializer<Calendar> {

    @Override
    public Calendar deserialize(JsonParser jsonparser, DeserializationContext context)
            throws IOException, JsonProcessingException {
        String dateAsString = jsonparser.getText();
        try {
            Date date = CustomCalendarSerializer.FORMATTER.parse(dateAsString);
            Calendar calendar = Calendar.getInstance(
                CustomCalendarSerializer.LOCAL_TIME_ZONE, 
                CustomCalendarSerializer.LOCALE_HUNGARIAN
            );
            calendar.setTime(date);
            return calendar;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

상기 클래스의 사용방법:

public class CalendarEntry {

    @JsonSerialize(using = CustomCalendarSerializer.class)
    @JsonDeserialize(using = CustomCalendarDeserializer.class)
    private Calendar calendar;

    // ... additional things ...
}

이 실장을 사용하면, 시리얼라이제이션 및 역시리얼라이제이션프로세스가 연속적으로 실행되어 원래의 값이 됩니다.

@JsonFormat 주석만 사용하면 라이브러리 내부 시간대의 기본 설정 때문에 주석 매개 변수로는 변경할 수 없는 다른 결과를 얻을 수 있습니다(그것이 잭슨 라이브러리 2.5.3 및 2.6.3 버전 사용 경험이기도 합니다).

날짜에 T 및 Z와 같은 문자를 추가하려면

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private Date currentTime;

산출량

{
    "currentTime": "2019-12-11T11:40:49Z"
}

이 예에서는 를 사용한Spring Boot 어플리케이션의 완전한 예를 나타냅니다.RFC3339datetime 형식

package bj.demo;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;

import java.text.SimpleDateFormat;

/**
 * Created by BaiJiFeiLong@gmail.com at 2018/5/4 10:22
 */
@SpringBootApplication
public class BarApp implements ApplicationListener<ApplicationReadyEvent> {

    public static void main(String[] args) {
        SpringApplication.run(BarApp.class, args);
    }

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
    }
}

@miklov-kriven의 매우 도움이 되는 답변을 바탕으로, 저는 이 두 가지 추가 고려 사항이 누군가에게 도움이 되기를 바랍니다.

(1) 시리얼라이저와 디시리얼라이저를 같은 클래스에 스태틱한 내부 클래스로 포함시키는 것이 좋습니다.NB, SimpleDateFormat의 스레드 안전을 위해 ThreadLocal을 사용합니다.

public class DateConverter {

    private static final ThreadLocal<SimpleDateFormat> sdf = 
        ThreadLocal.<SimpleDateFormat>withInitial(
                () -> {return new SimpleDateFormat("yyyy-MM-dd HH:mm a z");});

    public static class Serialize extends JsonSerializer<Date> {
        @Override
        public void serialize(Date value, JsonGenerator jgen SerializerProvider provider) throws Exception {
            if (value == null) {
                jgen.writeNull();
            }
            else {
                jgen.writeString(sdf.get().format(value));
            }
        }
    }

    public static class Deserialize extends JsonDeserializer<Date> {
        @Overrride
        public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws Exception {
            String dateAsString = jp.getText();
            try {
                if (Strings.isNullOrEmpty(dateAsString)) {
                    return null;
                }
                else {
                    return new Date(sdf.get().parse(dateAsString).getTime());
                }
            }
            catch (ParseException pe) {
                throw new RuntimeException(pe);
            }
        }
    }
}

(2) 각 클래스 멤버에서 @JsonSerialize 및 @JsonDeserialize 주석을 사용하는 대신 어플리케이션레벨에서 커스텀시리얼라이즈를 적용하여 잭슨의 디폴트시리얼라이즈를 덮어쓰는 것도 고려할 수 있습니다.즉, Date 타입의 모든 클래스멤버는 이 커스텀시리얼라이제이션 없이 이 커스텀시리얼라이즈를 사용하여 잭슨에 의해 시리얼라이즈 됩니다.각 필드에 xplicit 주석이 표시됩니다.예를 들어 Spring Boot를 사용하는 경우 다음과 같은 방법이 있습니다.

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public Module customModule() {
        SimpleModule module = new SimpleModule();
        module.addSerializer(Date.class, new DateConverter.Serialize());
        module.addDeserializer(Date.class, new Dateconverter.Deserialize());
        return module;
    }
}

날 위해 일하는 거지Spring Boot.

 import com.alibaba.fastjson.annotation.JSONField;

 @JSONField(format = "yyyy-MM-dd HH:mm:ss")  
 private Date createTime;

출력:

{ 
   "createTime": "2019-06-14 13:07:21"
}

java.sql에 대한 사용자 정의 날짜 형식을 사용하는 데 문제가 있는 경우.날짜, 이것이 가장 간단한 해결책입니다.

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(java.sql.Date.class, new DateSerializer());
mapper.registerModule(module);

(이 SO 답변으로 많은 수고를 덜 수 있었습니다.https://stackoverflow.com/a/35212795/3149048 )

Jackson은 기본적으로 java.sql에 SqlDateSerializer를 사용합니다.날짜. 단, 현재 이 시리얼라이저에서는 날짜 형식은 고려되지 않습니다.이 문제를 참조해 주세요.https://github.com/FasterXML/jackson-databind/issues/1407회피책은 java.sql에 다른 시리얼라이저를 등록하는 것입니다.코드 예시와 같은 날짜입니다.

이 설정을 지적하고 싶습니다.SimpleDateFormat다른 답변에서 설명한 바와 같이 동작하는 것은java.util.Date내 생각엔 그건 질문에서 의도된 것 같아.하지만 을 위해서java.sql.Date포메터가 작동하지 않습니다.제 경우 포맷터가 작동하지 않는 이유는 명확하지 않았습니다. 왜냐하면 직렬화되어야 할 모델에서 필드는 실제로 a였습니다.java.utl.Date하지만 실제 물체는 결국 비명을 지르고 말았다.java.sql.Date이 한 이유는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★

public class java.sql extends java.util.Date

그래서 이것은 실제로 유효하다.

java.util.Date date = new java.sql.Date(1542381115815L);

[] 의 형식이 않은 [Date]인지 합니다.java.util.Date.

여기에서는, 취급의 이유에 대해서도 언급하고 있습니다.java.sql.Date추가되지 않습니다.

이것은 변화를 깨는 것이 될 것이고, 나는 그것이 정당화될 수 있다고 생각하지 않는다.만약 우리가 처음부터 시작한다면 나는 그 변화에 동의하겠지만, 상황이 그렇게 심각하지는 않다.

언급URL : https://stackoverflow.com/questions/12463049/date-format-mapping-to-json-jackson

반응형