java.util.Date
가있는 Java 객체를 유지하려고합니다.
fasterxml jackson을 사용하는 몽고 컬렉션의필드
objectMapper의 기본 특성은 Date를 NumberLong 유형으로 저장하는 것입니다.
예 :
createdTime
java.util.Date
의필드
유형은 다음과 같이 저장됩니다 :
"createdTime" : NumberLong("1427728445176")
몽고 쉘에서 사용할 수있는ISODate형식으로 저장하고 싶습니다.
이제 객체 매퍼를 포맷하여 날짜를 문자열 날짜 형식으로 저장하는 방법이 있다는 것을 알고 있습니다. 하지만 ISODate () 형식 만 찾고 있습니다.
예 :
"createdTime" : ISODate("2015-01-20T16:39:42.132Z")
할 수있는 방법이 있습니까? 전문가에게 조언하십시오. 도움을 주셔서 감사합니다.
- 답변 # 1
- 답변 # 2
날짜 문자열을 ISODate 형식으로 직렬화 할 수있었습니다. 아래와 같이 고객 날짜 시리얼 라이저를 작성했습니다.
public void serialize(Date date, JsonGenerator jgen, SerializerProvider provider) throws IOException { String dateValue = getISODateString(date); String text = "{ \"$date\" : \""+ dateValue +"\"}"; jgen.writeRawValue(text); }
사용자 @ mmx73의 요청에 따라 고객 날짜 DeSeriaizer에 대한 코드를 추가하고 있습니다.
public class IsoDateDeSerializer extends JsonDeserializer<Date> { @Override public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { ObjectCodec oc = jsonParser.getCodec(); JsonNode node = oc.readTree(jsonParser); String dateValue = node.get("$date").asText(); //DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); Date date = null; try { date = df.parse(dateValue); } catch (ParseException e) { e.printStackTrace(); } return date; } }
- 답변 # 3
이 답변들 중 어느 것도 내가 원하는 것을 성취하지 못했습니다. JSON 문자열을 MongoDB에 직렬화 할 때 문자열로 저장 되었기 때문에 문제가 발생했습니다. 좋은 형식의 문자열이지만 문자열은 적습니다.
com.fasterxml.jackson.databind.ObjectMapper를 사용하여 객체를 JSON으로 /로부터 변환하고이 클래스를 계속 사용하고 싶습니다. 다음과 같은 방법이 있습니다 :
public enum JsonIntent {NONE, MONGODB}; public static ObjectMapper getMapper(final JsonIntent intent) { ObjectMapper mapper = new ObjectMapper(); // Setting to true saves the date as NumberLong("1463597707000") // Setting to false saves the data as "2016-05-18T19:30:52.000+0000" mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.registerModule(new JodaModule()); if (intent == JsonIntent.MONGODB) { // If you want a date stored in MONGO as a date, then you must store it in a way that MONGO // is able to deal with it. SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null, null, null)); testModule.addSerializer(Date.class, new StdSerializer<Date>(Date.class) { private static final long serialVersionUID = 1L; @Override public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException { try { if (value == null) { jgen.writeNull(); } else { jgen.writeStartObject(); jgen.writeFieldName("$date"); String isoDate = ISODateTimeFormat.dateTime().print(new DateTime(value)); jgen.writeString(isoDate); jgen.writeEndObject(); } } catch (Exception ex) { Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, "Couldn't format timestamp " + value + ", writing 'null'", ex); jgen.writeNull(); } } }); testModule.addDeserializer(Date.class, new StdDeserializer<Date>(Date.class) { private static final long serialVersionUID = 1L; @Override public Date deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException { JsonNode tree = jp.readValueAsTree(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); try { return ISODateTimeFormat.dateTime().parseDateTime(tree.get("$date").textValue()).toDate(); } catch (Throwable t) { throw new IOException(t.getMessage(), t); } } }); mapper.registerModule(testModule); } return mapper; }
이제 다음 테스트 코드를 실행할 수 있습니다 :
BObjectMapper mapper = getMapper(JsonUtil.JsonIntent.NONE); Date d1 = new Date(); String v = mapper.writeValueAsString(d1); System.out.println("Joda Mapping: " + v); Date d2 = mapper.readValue(v, Date.class); System.out.println("Decoded Joda: " + d2); mapper = getMapper(JsonUtil.JsonIntent.MONGODB); v = mapper.writeValueAsString(d1); System.out.println("Mongo Mapping: " + v); d2 = mapper.readValue(v, Date.class); System.out.println("Decoded Mongo: " + d2);
출력은 다음과 같습니다 :
Joda Mapping: "2016-06-13T14:58:11.937+0000" Decoded Joda: Mon Jun 13 10:58:11 EDT 2016 Mongo Mapping: {"$date":"2016-06-13T10:58:11.937-04:00"} Decoded Mongo: Mon Jun 13 10:58:11 EDT 2016
MONGODB로 전송 될 JSON은 "$date"라는 필드를 포함하는 값을 정의합니다. 이것은 MongoDB에게 이것이 날짜 개체라고 알려줍니다.
Mongo를 보면 다음이 표시됩니다.
"importDate" : ISODate("2016-05-18T18:55:07Z")
이제 문자열이 아닌 날짜로 필드에 액세스 할 수 있습니다.
몽고에 인코딩 된 JSON 문자열을 추가하기 위해 내 코드는 다음과 같습니다.
이 경우 "json"은 인코딩 된 JSON 문자열입니다. JSON 문자열에서 가져 오기 때문에 유추하지 않는 한 유형을 알 수있는 방법이 없으므로 "$date"부분이 필요합니다. "버킷"은 사용할 테이블을 나타내는 문자열입니다. 참고로, Mongo에서 BSON 객체를 가져 와서 doc.toJson ()을 호출하여 JSON 문자열로 변환하면 doc은 쿼리에서 반환 된 org.bison.Document 유형입니다. ) 날짜 개체는 형식이 지정된 텍스트 문자열이 아닌 긴 값으로 저장됩니다. 이런 식으로 포맷 한 후 데이터를 mongo로 푸시 할 수 있는지 확인하지 않았지만 다음과 같이 지원하도록 위에 표시된 deserializer를 수정할 수 있습니다.MongoDatabase db = getDatabase(); Document d = Document.parse(json); db.getCollection(bucket).insertOne(d);
testModule.addDeserializer(Date.class, new StdDeserializer<Date>(Date.class) { private static final long serialVersionUID = 1L; @Override public Date deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException { JsonNode tree = jp.readValueAsTree(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); try { // Mongo will return something that looks more like: // {$date:<long integer for milliseconds>} // so handle that as well. JsonNode dateNode = tree.get("$date"); if (dateNode != null) { String textValue = dateNode.textValue(); if (!Util.IsNullOrEmpty(textValue)) { return ISODateTimeFormat.dateTime().parseDateTime(textValue).toDate(); } return Util.MillisToDate(dateNode.asLong()); } return null; } catch (Throwable t) { Util.LogIt("Exception: " + t.getMessage()); throw new IOException(t.getMessage(), t); } } });
다음과 같이 밀리 초를 Date 또는 DateTime으로 변환 할 수 있습니다.
/** * Convert milliseconds to a date time. If zero or negative, just return * null. * * @param milliseconds * @return */ public static Date MillisToDate(final long milliseconds) { if (milliseconds < 1) { return null; } Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(milliseconds); return calendar.getTime(); } public static DateTime MillisToDateTime(final long milliseconds) { if (milliseconds < 1) { return null; } return new DateTime(milliseconds); }
- 답변 # 4
같은 메시지가 나타나는 경우
com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value
.writeRawValue
를 사용하십시오 대신 허용 된 답변 내에서. 필드가 올바르게 종료됩니다. 그렇지 않으면 직렬화 할 다음 필드에이 오류가 발생할 수 있습니다.
관련 자료
- postgresql - sql - `cron` 필드 저장 및 쿼리
- 장고 모델을 사용하여 데이터베이스에 Enter 키워드를 사용하여 문자 필드를 한 줄씩 저장하는 방법은 무엇입니까?
- JavaScript를 사용하여 JSON 개체의 일부를 구문 분석하고 저장하는 방법
- java - Spring Boot MiroService에서 Jackson API를 사용하는 동안 JSON 변환 오류
- dictionary - 특정 필드를 키로 사용하여 구조체를 맵으로 변환하는 방법은 무엇입니까?
- drupal - entityQuery를 사용하여 부모의 필드 이름으로 단락을 필터링하는 방법은 무엇입니까?
- sql server - Mysql 오류를 사용하는 필드 목록의 알 수없는 열
- 앵귤러 머티리얼을 사용하고 있습니다 입력 필드를 이메일로 보내는 방법
- '고유'에 대한 번역 필드를 사용하면 NameError, django-parler가 발생합니다
- Scheme define-syntax 매크로를 사용하여 레코드 필드를 증가시키는 방법
- 필드 코드를 사용하여 Word 문서에서 일부 페이지의 페이지 번호를 숨기는 방법은 무엇입니까?
- django - jQuery를 사용하여 입력 필드에 '목록'속성을 어떻게 추가합니까?
- php - laravel eloquest를 사용하여 스위치 케이스를 사용하여 특정 필드 업데이트
- reactjs - React를 사용하여 재사용 가능한 입력 필드를 만드는 방법은 무엇입니까?
- php - ORDER BY 및 FIELD 함수를 사용하여 각 사용자 지정 목록에 단일 값 가져 오기
- c# - 개체 및 메서드를 사용하여 구분 기호로 구분 된 목록에 텍스트 저장
- How to allow user to input and store array using loops - 사용자가 루프를 사용하여 배열을 입력하고 저장하도록 허용하는 방법-Python
- reactjs - 머티리얼 UI에서 슬라이더를 사용하여 mobx 스토어를 업데이트하는 방법
- java : 잭슨은 객체를 문자열로 변환하고 속성 유형은 정수이고 getter는 int를 반환합니다. 속성이 null일 때 null 포인트 예외가 발생합니까?
- java : 스프링 부트가 요청 사이에 세션과 쿠키를 저장하지 않는 이유는 무엇입니까?
- MongoDb 날짜 오류 Java
- java : JSON 구문 분석 시 잭슨 오류 "잘못된 문자... 일반 공백만 허용됨"
- java : .dao.DataIntegrityViolationException: 제한된 컬렉션에서 문서의 크기를 변경할 수 없습니다: 311 != 333;
- MongoDB/Java Spring Boot에서 월별 카운트 얻기
- java : Jackson: 객체 배열의 역직렬화
- java : Lombok을 사용하여 "has" 관계를 올바르게 포함하는 방법은 무엇입니까?
- java : Apache Camel Mongodb 커넥터 비동기
- Java Spring -리소스 폴더의 기존 파일에 쓰기
필요한 것은 Jackson Joda Module입니다. 클래스 패스로 가져 오면 매퍼에서 다음을 수행하여 원하는 타임 스탬프로 쓸 수 있습니다.
date
를 교체 할 수 있습니다 필요에 따라 위의 코드 샘플에서 POJO를 사용하십시오.편집 : 실제로 원하는 것은 사용자 정의 직렬 변환기입니다. 다음과 같이 보일 것입니다 :
그러면 모든 DateTime 유형에 대해 매퍼에 등록합니다
주석을 사용하여 함수에 지정