Mongo C#driver toJson()DateTime

时间:2017-10-20 10:18:28

标签: c# json mongodb datetime

我在mongo中有数据,如下所示:

"trd" : ISODate("2003-12-08T00:00:00Z")

现在,我正在从Mongo获取数据作为BsonDocument,如下所示:

 var builder = Builders<BsonDocument>.Filter;
            var filter = builder.Eq("wsid", id);
            var mongoListBatch = _client.GetManyByFilter(filter, "directory");
            JsonWriterSettings settings = new JsonWriterSettings();
            settings.OutputMode = JsonOutputMode.Strict;

            var lists = mongoListBatch.ToJson(settings);

问题是我希望在json中获取这样的DateTime对象:

 "transactiedatum": "23-02-1993"

但相反,我得到:

 "transactiedatum": {
          "$date": 1070841600000
        }

首先,它的unix时间格式,第二,json结构有变化。我怎么处理这个?

1 个答案:

答案 0 :(得分:1)

我们遇到了类似的问题。这听起来很复杂,但这并不是什么大不了的事。

首先,这里是github上Mongo C#驱动的链接: MongoC#Driver

对你而言,这些是其中的两个重要链接:

  1. Bson Extension Methods
  2. JsonWriter
  3. JsonWriterContext
  4. 我们想要实现的是我们不希望我们的Json字符串中的表示形式为unix时间戳格式,因此我们将这些类复制到具有不同名称的项目中,因此,以下是所有这些:< / p>

    扩展类:

    using System;
    using System.IO;
    using MongoDB.Bson.IO;
    using MongoDB.Bson.Serialization;
    using MongoDB.Bson;
    
        namespace Fishing.MongoDB.Serializers
        {
            public static class MyJsonWriterSettings
            {
    
                /// <summary>
                /// Serializes an object to a BSON byte array.
                /// </summary>
                /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
                /// <param name="obj">The object.</param>
                /// <param name="serializer">The serializer.</param>
                /// <param name="writerSettings">The writer settings.</param>
                /// <param name="configurator">The serialization context configurator.</param>
                /// <param name="args">The serialization args.</param>
                /// <returns>A BSON byte array.</returns>
                public static byte[] ToBson<TNominalType>(
                    this TNominalType obj,
                    IBsonSerializer<TNominalType> serializer = null,
                    BsonBinaryWriterSettings writerSettings = null,
                    Action<BsonSerializationContext.Builder> configurator = null,
                    BsonSerializationArgs args = default(BsonSerializationArgs)
                    )
                {
                    return ToBson(obj, typeof(TNominalType), writerSettings, serializer, configurator, args);
                }
    
                /// <summary>
                /// Serializes an object to a BSON byte array.
                /// </summary>
                /// <param name="obj">The object.</param>
                /// <param name="nominalType">The nominal type of the object..</param>
                /// <param name="writerSettings">The writer settings.</param>
                /// <param name="serializer">The serializer.</param>
                /// <param name="configurator">The serialization context configurator.</param>
                /// <param name="args">The serialization args.</param>
                /// <returns>A BSON byte array.</returns>
                /// <exception cref="System.ArgumentNullException">nominalType</exception>
                /// <exception cref="System.ArgumentException">serializer</exception>
                public static byte[] ToBson(
                    this object obj,
                    Type nominalType,
                    BsonBinaryWriterSettings writerSettings = null,
                    IBsonSerializer serializer = null,
                    Action<BsonSerializationContext.Builder> configurator = null,
                    BsonSerializationArgs args = default(BsonSerializationArgs))
                {
                    if (nominalType == null)
                    {
                        throw new ArgumentNullException("nominalType");
                    }
    
                    if (serializer == null)
                    {
                        serializer = BsonSerializer.LookupSerializer(nominalType);
                    }
                    if (serializer.ValueType != nominalType)
                    {
                        var message = string.Format("Serializer type {0} value type does not match document types {1}.", serializer.GetType().FullName, nominalType.FullName);
                        throw new ArgumentException(message, "serializer");
                    }
    
                    using (var memoryStream = new MemoryStream())
                    {
                        using (var bsonWriter = new BsonBinaryWriter(memoryStream, writerSettings ?? BsonBinaryWriterSettings.Defaults))
                        {
                            var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator);
                            args.NominalType = nominalType;
                            serializer.Serialize(context, args, obj);
                        }
                        return memoryStream.ToArray();
                    }
                }
    
                /// <summary>
                /// Serializes an object to a BsonDocument.
                /// </summary>
                /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
                /// <param name="obj">The object.</param>
                /// <param name="serializer">The serializer.</param>
                /// <param name="configurator">The serialization context configurator.</param>
                /// <param name="args">The serialization args.</param>
                /// <returns>A BsonDocument.</returns>
                public static BsonDocument ToBsonDocument<TNominalType>(
                    this TNominalType obj,
                    IBsonSerializer<TNominalType> serializer = null,
                    Action<BsonSerializationContext.Builder> configurator = null,
                    BsonSerializationArgs args = default(BsonSerializationArgs))
                {
                    return ToBsonDocument(obj, typeof(TNominalType), serializer, configurator, args);
                }
    
                /// <summary>
                /// Serializes an object to a BsonDocument.
                /// </summary>
                /// <param name="obj">The object.</param>
                /// <param name="nominalType">The nominal type of the object.</param>
                /// <param name="serializer">The serializer.</param>
                /// <param name="configurator">The serialization context configurator.</param>
                /// <param name="args">The serialization args.</param>
                /// <returns>A BsonDocument.</returns>
                /// <exception cref="System.ArgumentNullException">nominalType</exception>
                /// <exception cref="System.ArgumentException">serializer</exception>
                public static BsonDocument ToBsonDocument(
                    this object obj,
                    Type nominalType,
                    IBsonSerializer serializer = null,
                    Action<BsonSerializationContext.Builder> configurator = null,
                    BsonSerializationArgs args = default(BsonSerializationArgs))
                {
                    if (nominalType == null)
                    {
                        throw new ArgumentNullException("nominalType");
                    }
    
                    if (obj == null)
                    {
                        return null;
                    }
    
                    if (serializer == null)
                    {
                        var bsonDocument = obj as BsonDocument;
                        if (bsonDocument != null)
                        {
                            return bsonDocument; // it's already a BsonDocument
                        }
    
                        var convertibleToBsonDocument = obj as IConvertibleToBsonDocument;
                        if (convertibleToBsonDocument != null)
                        {
                            return convertibleToBsonDocument.ToBsonDocument(); // use the provided ToBsonDocument method
                        }
    
                        serializer = BsonSerializer.LookupSerializer(nominalType);
                    }
                    if (serializer.ValueType != nominalType)
                    {
                        var message = string.Format("Serializer type {0} value type does not match document types {1}.", serializer.GetType().FullName, nominalType.FullName);
                        throw new ArgumentException(message, "serializer");
                    }
    
                    // otherwise serialize into a new BsonDocument
                    var document = new BsonDocument();
                    using (var bsonWriter = new BsonDocumentWriter(document))
                    {
                        var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator);
                        args.NominalType = nominalType;
                        serializer.Serialize(context, args, obj);
                    }
                    return document;
                }
    
                /// <summary>
                /// Serializes an object to a JSON string.
                /// </summary>
                /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
                /// <param name="obj">The object.</param>
                /// <param name="writerSettings">The JsonWriter settings.</param>
                /// <param name="serializer">The serializer.</param>
                /// <param name="configurator">The serializastion context configurator.</param>
                /// <param name="args">The serialization args.</param>
                /// <returns>
                /// A JSON string.
                /// </returns>
                public static string ToMyJson<TNominalType>(
                    this TNominalType obj,
                    JsonWriterSettings writerSettings = null,
                    IBsonSerializer<TNominalType> serializer = null,
                    Action<BsonSerializationContext.Builder> configurator = null,
                    BsonSerializationArgs args = default(BsonSerializationArgs))
                {
                    return ToMyJson(obj, typeof(TNominalType), writerSettings, serializer, configurator, args);
                }
    
                /// <summary>
                /// Serializes an object to a JSON string.
                /// </summary>
                /// <param name="obj">The object.</param>
                /// <param name="nominalType">The nominal type of the objectt.</param>
                /// <param name="writerSettings">The JsonWriter settings.</param>
                /// <param name="serializer">The serializer.</param>
                /// <param name="configurator">The serialization context configurator.</param>
                /// <param name="args">The serialization args.</param>
                /// <returns>
                /// A JSON string.
                /// </returns>
                /// <exception cref="System.ArgumentNullException">nominalType</exception>
                /// <exception cref="System.ArgumentException">serializer</exception>
                public static string ToMyJson(
                    this object obj,
                    Type nominalType,
                    JsonWriterSettings writerSettings = null,
                    IBsonSerializer serializer = null,
                    Action<BsonSerializationContext.Builder> configurator = null,
                    BsonSerializationArgs args = default(BsonSerializationArgs))
                {
                    if (nominalType == null)
                    {
                        throw new ArgumentNullException("nominalType");
                    }
    
                    if (serializer == null)
                    {
                        serializer = BsonSerializer.LookupSerializer(nominalType);
                    }
                    if (serializer.ValueType != nominalType)
                    {
                        var message = string.Format("Serializer type {0} value type does not match document types {1}.", serializer.GetType().FullName, nominalType.FullName);
                        throw new ArgumentException(message, "serializer");
                    }
    
                    using (var stringWriter = new StringWriter())
                    {
                        using (var bsonWriter = new JsonWriterMine(stringWriter, writerSettings ?? JsonWriterSettings.Defaults))
                        {
                            var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator);
                            args.NominalType = nominalType;
                            serializer.Serialize(context, args, obj);
                        }
                        return stringWriter.ToString();
                    }
                }
            }
        }
    

    所以基本上,将整个类从github复制到你自己的类中,并将2个方法的名称:ToJson()更改为你的一个。在这里你可以看到我的是ToJsonMine()。

    现在,您将需要第二节课:

    JsonWriter

    using MongoDB.Bson.IO;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using MongoDB.Bson;
    
    namespace Fishing.MongoDB.Serializers
    {
        public class JsonWriterMine : BsonWriter
        {
    
            // private fields
            private TextWriter _textWriter;
            private JsonWriterSettings _jsonWriterSettings; // same value as in base class just declared as derived class
            private InternalJsonWriterContext _context;
    
            // constructors
            /// <summary>
            /// Initializes a new instance of the JsonWriter class.
            /// </summary>
            /// <param name="writer">A TextWriter.</param>
            public JsonWriterMine(TextWriter writer)
                : this(writer, JsonWriterSettings.Defaults)
            {
            }
    
            /// <summary>
            /// Initializes a new instance of the JsonWriter class.
            /// </summary>
            /// <param name="writer">A TextWriter.</param>
            /// <param name="settings">Optional JsonWriter settings.</param>
            public JsonWriterMine(TextWriter writer, JsonWriterSettings settings)
                : base(settings)
            {
                if (writer == null)
                {
                    throw new ArgumentNullException("writer");
                }
    
                _textWriter = writer;
                _jsonWriterSettings = settings; // already frozen by base class
                _context = new InternalJsonWriterContext(null, ContextType.TopLevel, "");
                State = BsonWriterState.Initial;
            }
    
     /// <summary>
        /// Writes a BSON DateTime to the writer.
        /// </summary>
        /// <param name="value">The number of milliseconds since the Unix epoch.</param>
        public override void WriteDateTime(long value)
        {
            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
            {
                ThrowInvalidState("WriteDateTime", BsonWriterState.Value, BsonWriterState.Initial);
            }
    
            WriteNameHelper(Name);
            switch (_jsonWriterSettings.OutputMode)
            {
                case JsonOutputMode.Strict:
                    var utcDateTimeFirst = BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(value);
                    _textWriter.Write($"\"{utcDateTimeFirst.ToString("yyyy-MM-ddTHH:mm:ss.FFFZ")}\"");
                    break;
    
                case JsonOutputMode.Shell:
                default:
                    // use ISODate for values that fall within .NET's DateTime range, and "new Date" for all others
                    if (value >= BsonConstants.DateTimeMinValueMillisecondsSinceEpoch &&
                        value <= BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch)
                    {
                        var utcDateTime = BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(value);
                        _textWriter.Write("ISODate(\"{0}\")", utcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.FFFZ"));
                    }
                    else
                    {
                        _textWriter.Write("new Date({0})", value);
                    }
                    break;
            }
    
            State = GetNextState();
        }
    
        }
    }
    

    这就是魔术发生的地方。将整个类JsonWriter从GitHub复制到您自己的名称中,并为其指定一个新名称(Extend BsonWriter nad实现所有方法)。现在,您可以在这里操纵您希望如何序列化日期。相应地更改WriteDateTime(long value)。正如您所看到的,在case JsonOutputMode.Strict:中,我将其更改为返回一个DateTime对象,格式化为我需要的方式。

    最后,由于MongoSerializer具有名为JsonWriterContext的内部类,因此您需要创建自己的类并在JsonWriter中使用它(步骤2)。

    这就是我的样子(你可以整个复制):

    using MongoDB.Bson.IO;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Fishing.MongoDB.Serializers
    {
        public class InternalJsonWriterContext
        {
            // private fields
            private InternalJsonWriterContext _parentContext;
            private ContextType _contextType;
            private string _indentation;
            private bool _hasElements = false;
    
            // constructors
            internal InternalJsonWriterContext(InternalJsonWriterContext parentContext, ContextType contextType, string indentChars)
            {
                _parentContext = parentContext;
                _contextType = contextType;
                _indentation = (parentContext == null) ? indentChars : parentContext.Indentation + indentChars;
            }
    
            // internal properties
            internal InternalJsonWriterContext ParentContext
            {
                get { return _parentContext; }
            }
    
            internal ContextType ContextType
            {
                get { return _contextType; }
            }
    
            internal string Indentation
            {
                get { return _indentation; }
            }
    
            internal bool HasElements
            {
                get { return _hasElements; }
                set { _hasElements = value; }
            }
        }
    }
    

    拥有所有内容后,您将在MongoCursorJsonConverter(第1步)中看到第二个ToJsonMine()方法,我有这一行:

     using (var bsonWriter = new JsonWriterMine(stringWriter, writerSettings ?? JsonWriterSettings.Defaults))
    

    您应该将它替换为您在步骤2中创建的自定义类,它将像魅力一样工作。

    最后,你只需致电:

    var lists = mongoListBatch.ToJson(settings);
    

    它将序列化您在WriteDate(long value)

    中添加的日期