bestsource

날짜 역직렬화를 위한 잭슨 표준 시간대 설정

bestsource 2023. 2. 13. 20:35
반응형

날짜 역직렬화를 위한 잭슨 표준 시간대 설정

스프링 을를 잭슨(Spring MVC 주석 사용)으로java.util.Date입니다. - POST처럼 있습니다.{"enrollDate":"2011-09-28T00:00:00.000Z"} Spring & 가 ,, Spring & Jackson으로 "2011-09-27 20:00:00"

잭슨에서 적절한 시간대를 설정하려면 어떻게 해야 하나요? 아니면 JSON 메시지에서 EST를 보내려면 어떻게 해야 하나요?

Javascript/jQuery:

var personDataView = { enrollDate : new Date($("#enrollDate").val()), 
                       //...other members
                      };


$.postJSON('/some/path/', personDataView, function(data){
    //... handle the response here

});

JSON 메시지:

{"enrollDate":"2011-09-28T00:00:00.000Z"}

스프링 컨트롤러:

@RequestMapping(value="/", method=RequestMethod.POST)
public @ResponseBody String saveProfile(@RequestBody personDataView persondataView, HttpServletRequest request)
{
        //...dataView has a java.util.Date enrollDate field
        //...other code
}

잭슨 2+에서는 @JsonFormat 주석을 사용할 수도 있습니다.

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone="America/Phoenix")
private Date date;

이 방법으로 동작하지 않는 경우는, 작은 따옴표로 Z를 감싸 주세요(예: pattern="yyy-MM-d'T').HH:mm:ss.SSS'Z'"

사용하시는 application.properties에서 사용해 보셨습니까?

spring.jackson.time-zone= # Time zone used when formatting dates. For instance `America/Los_Angeles`

Jackson이 UTC가 아닌 다른 시간대의 날짜를 반환하고 싶다면(특히 일부 클라이언트가 시간대 부분을 얻지 못한 경우) 저는 보통 다음과 같이 합니다.

ObjectMapper mapper = new ObjectMapper();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
dateFormat.setTimeZone(TimeZone.getTimeZone("CET"));
mapper.getSerializationConfig().setDateFormat(dateFormat);
// ... etc

시간대를 이해하는 사람에게는 악영향이 없습니다.

Jackson 1.9.7을 사용하고 있는데, 다음 작업을 수행해도 시리얼화/디시리얼화 타임존 문제가 해결되지 않습니다.

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
objectMapper.setDateFormat(dateFormat);

''2014-02-13' '으로 표시됨T20:09:09.859Z "2014-02-13" "T08 않습니다T08:09:09.859+0000" 입니다.가 발생하는 만, Jackson이 한 소스코드를 만 하면 것을 알 수 있습니다.ISO8601DateFormat의 클래스ObjectMapper.setDateFormat 방법

, 에, 「 」, 「 」, 「 」를 서브 .ISO8601DateFormat 및 합니다.format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition)★★★★★★ 。

/**
 * Provides a ISO8601 date format implementation that includes milliseconds
 *
 */
public class ISO8601DateFormatWithMillis extends ISO8601DateFormat {

  /**
   * For serialization
   */
  private static final long serialVersionUID = 2672976499021731672L;


  @Override
  public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition)
  {
      String value = ISO8601Utils.format(date, true);
      toAppendTo.append(value);
      return toAppendTo;
  }
}

의 오래된 것 만, 그 이유는 "Jackson의 오래된 버전이기 때문입니다.objectMappersetTimeZone(tz)무시됩니다.dateFormat의 타임존 설정은 무시됩니다.

잭슨 버전 2.11.0에서 오브젝트 맵퍼에 timeZone을 올바르게 설정하는 방법:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Warsaw"));

완전한 예

  @Test
  void test() throws Exception {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.findAndRegisterModules();
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    JavaTimeModule module = new JavaTimeModule();
    objectMapper.registerModule(module);
    objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Warsaw"));

    ZonedDateTime now = ZonedDateTime.now();
    String converted = objectMapper.writeValueAsString(now);

    ZonedDateTime restored = objectMapper.readValue(converted, ZonedDateTime.class);
    System.out.println("serialized: " + now);
    System.out.println("converted: " + converted);
    System.out.println("restored: " + restored);

    Assertions.assertThat(now).isEqualTo(restored);
  }
`

방금 이 문제를 발견했는데 LocalDateTime에 시간대 정보가 없다는 것을 알게 되었습니다.시간대 정보가 포함된 날짜 문자열을 받은 경우 다음을 유형으로 사용해야 합니다.

존 날짜 시간

링크를 확인합니다.

날짜를 ISO 형식으로 GMT 시간대로 인코딩하여 전송하고 날짜를 인쇄할 때 EST에 있기 때문에 날짜 개체는 문제가 없을 수 있습니다.

날짜 개체는 인쇄되는 시점에 시간대 변환을 수행합니다.다음 중 어느 쪽이date오브젝트는 다음과 같습니다.

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTime(date);
System.out.println (cal);

Calendar Diserializer 확장 문제를 해결하여 Calendar deserializer 확장 문제를 해결했습니다.
UTC 시간대를 강제 적용합니다.
누군가 필요한 경우 코드를 붙여넣습니다.

@JacksonStdImpl
public class UtcCalendarDeserializer extends CalendarDeserializer {

    TimeZone TZ_UTC = TimeZone.getTimeZone("UTC");

    @Override
    public Calendar deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonToken t = jp.getCurrentToken();
        if (t == JsonToken.VALUE_NUMBER_INT) {
            Calendar cal = Calendar.getInstance(TZ_UTC);
            cal.clear();
            cal.setTimeInMillis(jp.getLongValue());

            return cal;
        }

        return super.deserialize(jp, ctxt);
    }
}

JSON 모델 클래스의 경우 필드에 주석을 달기만 하면 됩니다.

@JsonDeserialize(using = UtcCalendarDeserializer.class)
private Calendar myCalendar;

지금(2020년 2월)에 이 문제로 고민하고 있는 사람에게 있어서, 다음의 Medium 포스트는 그것을 극복하는데 있어서 불가결했습니다.

https://medium.com/ @ttulka / spring - message - customizing - 770814eb2b55

이 경우 앱은 @EnableWebMvc를 사용하므로 삭제 시 파손되기 때문에 '스프링 부트 없는 삶' 섹션이 중요했습니다.이 문제를 해결하게 된 계기는 다음과 같습니다.JSON과 XML을 계속 소비하고 제작할 수 있을 뿐만 아니라 앱의 요구에 맞게 시리얼라이제이션 중에 날짜 시간을 포맷할 수 있습니다.

@Configuration
@ComponentScan("com.company.branch")
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(0, new MappingJackson2XmlHttpMessageConverter(
                new Jackson2ObjectMapperBuilder()
                        .defaultUseWrapper(false)
                        .createXmlMapper(true)
                        .simpleDateFormat("yyyy-mm-dd'T'HH:mm:ss'Z'")
                        .build()
        ));
    converters.add(1, new MappingJackson2HttpMessageConverter(
                new Jackson2ObjectMapperBuilder()
                        .build()
        ));
    }
}

언급URL : https://stackoverflow.com/questions/7556851/set-jackson-timezone-for-date-deserialization

반응형