2016-06-24 2 views
2
  1. Использование java-драйвера MongoDB, применяя метод toJson() в документе, получит представление JSON этого документа с JsonMode, установленным в STRICT. Для дат используется следующий формат эпохи: {"$ date": "dateAsMilliseconds"}Формат даты MongoDB в строгом режиме

  2. Используя mongoexport, мы получаем ISO-8601 формат.

  3. посещение в официальном док (https://docs.mongodb.com/manual/reference/mongodb-extended-json/):

    • в строгом режиме, дата является ISO-8601 формат даты с обязательным полем часового пояса после шаблона YYYY-MM-ДДTчч: мм: сс .mmm < +/- Offset>.

    • В настоящее время парсер MongoDB JSON не поддерживает загрузку строк ISO-8601, представляющих даты до эпохи Unix. При форматировании даты до эпох и даты прошлой какого типа time_t вашей системы может быть выполнен, используется следующий формат: { «дата $»: { «$ numberLong»: «dateAsMilliseconds»}}

Буду признателен, если кто-нибудь сможет объяснить мне, почему нет общего формата, используемого между Java-драйвером MongoDB, средством mongoexport и официальными документами?

Спасибо.

ответ

0

Очевидно, что есть NO. Хорошая причина, по которой драйвер Java отклоняется от официальной спецификации. Единственное исключение - это те даты, которые не могут быть выражены в формате ISO8601 (например, даты BC ...)

В качестве работы я расширил класс JsonWriter и предоставил два статических метода toJson в качестве примера того, как использовать его:

package whatever.package.you.like; 

import java.io.IOException; 
import java.io.StringWriter; 
import java.io.Writer; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.TimeZone; 

import org.bson.BSONException; 
import org.bson.BsonContextType; 
import org.bson.BsonDocument; 
import org.bson.codecs.BsonDocumentCodec; 
import org.bson.codecs.EncoderContext; 
import org.bson.conversions.Bson; 
import org.bson.json.JsonMode; 
import org.bson.json.JsonWriter; 
import org.bson.json.JsonWriterSettings; 

import com.mongodb.MongoClient; 

/** 
* A {@link JsonWriter} extension that conforms to the "strict" JSON format 
* specified by MongoDB for data/time values. 
* 
* The {@link JsonWriter} class provided in the MongoDB Java driver (version 
* 3.2.2) does not conform to official MongoDB specification for strict mode 
* JSON (see https://docs.mongodb.com/manual/reference/mongodb-extended-json/). 
* This is specifically a problem with the date/time values which get filled 
* with a milliseconds value (i.e. {$date: 309249234098}) instead of the ISO8601 
* date/time (i.e. {$date: "2016-07-14T08:44:23.234Z"}) value which the 
* specification calls for. This extension of {@link JsonWriter} conforms to the 
* MongoDb specification in this regard. 
*/ 
public class ConformingJsonWriter extends JsonWriter { 
    private final JsonWriterSettings settings; 

    private final Writer writer; 

    private boolean writingIndentedDateTime = false; 

    /** 
    * Creates a new instance which uses {@code writer} to write JSON to. 
    * 
    * @param writer 
    *   the writer to write JSON to. 
    */ 
    public ConformingJsonWriter(final Writer writer) { 
     this(writer, new JsonWriterSettings()); 
    } 

    /** 
    * Creates a new instance which uses {@code writer} to write JSON to and uses 
    * the given settings. 
    * 
    * @param writer 
    *   the writer to write JSON to. 
    * @param settings 
    *   the settings to apply to this writer. 
    */ 
    public ConformingJsonWriter(final Writer writer, 
     final JsonWriterSettings settings) { 
     super(writer, settings); 
     this.writer = writer; 
     this.settings = settings; 
     setContext(new Context(null, BsonContextType.TOP_LEVEL, "")); 
    } 

    private void writeIndentation(int skip) throws IOException { 
     for (Context context = getContext() 
      .getParentContext(); context != null; context = context 
        .getParentContext()) { 
     if (skip-- <= 0) { 
      writer.write(settings.getIndentCharacters()); 
     } 
     } 
    } 

    private static String millisToIso8601(long millis) throws IOException { 
     SimpleDateFormat dateFormat = new SimpleDateFormat(
      "yyyy-MM-dd\'T\'HH:mm:ss.SSS\'Z\'"); 
     dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 
     return dateFormat.format(new Date(millis)); 
    } 

    @Override 
    protected void doWriteDateTime(final long value) { 
     if ((settings.getOutputMode() == JsonMode.STRICT) 
      && (value >= -59014396800000L && value <= 253399536000000L)) { 
     try { 
      writeStartDocument(); 
      if (settings.isIndent()) { 
       writingIndentedDateTime = true; 
       writer.write(settings.getNewLineCharacters()); 
       writeIndentation(0); 
      } else { 
       writer.write(" "); 
      } 
      writer.write("\"$date\" : "); 
      writer.write("\""); 
      writer.write(millisToIso8601(value)); 
      writer.write("\""); 
      writeEndDocument(); 
      writingIndentedDateTime = false; 
     } catch (IOException e) { 
      throw new BSONException("Wrapping IOException", e); 
     } 
     } else { 
     super.doWriteDateTime(value); 
     } 
    } 

    @Override 
    protected void doWriteEndDocument() { 
     if (writingIndentedDateTime) { 
     try { 
      writer.write(settings.getNewLineCharacters()); 
      writeIndentation(1); 
      writer.write("}"); 
      if (getContext() 
        .getContextType() == BsonContextType.SCOPE_DOCUMENT) { 
       setContext(getContext().getParentContext()); 
       writeEndDocument(); 
      } else { 
       setContext(getContext().getParentContext()); 
      } 
     } catch (IOException e) { 
      throw new BSONException("Wrapping IOException", e); 
     } 
     } else { 
     super.doWriteEndDocument(); 
     } 
    } 

    /** 
    * Take a {@link Bson} instance and convert it to "strict" JSON 
    * representation with no indentation (read, "NOT pretty printed"). 
    * 
    * @param bson 
    *   The {@link Bson} instance to convert 
    * @return The JSON representation. 
    */ 
    public static String toJson(Bson bson) { 
     return toJson(bson, new JsonWriterSettings()); 
    } 

    /** 
    * Take a {@link Bson} instance and convert it to JSON representation. 
    * 
    * @param bson 
    *   The {@link Bson} instance to convert 
    * @param writerSettings 
    *   {@link JsonWriterSettings} that specify details about how the 
    *   JSON output should look. 
    * @return The JSON representation. 
    */ 
    public static String toJson(Bson bson, 
     final JsonWriterSettings writerSettings) { 
     BsonDocumentCodec encoder = new BsonDocumentCodec(); 
     ConformingJsonWriter writer = new ConformingJsonWriter(new StringWriter(), 
      writerSettings); 
     encoder.encode(writer, 
      bson.toBsonDocument(BsonDocument.class, 
        MongoClient.getDefaultCodecRegistry()), 
      EncoderContext.builder().isEncodingCollectibleDocument(true) 
        .build()); 
     return writer.getWriter().toString(); 
    } 
} 
Смежные вопросы