简体   繁体   English

Mongo C#driver toJson()DateTime

[英]Mongo C# driver toJson() DateTime

I have data in mongo which is like this: 我在mongo中有数据,如下所示:

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

Now, I am doing getting of data from Mongo as BsonDocument like this: 现在,我正在从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);

The problem is that I am expecting to get DateTime object like this inside the json: 问题是我希望在json中获取这样的DateTime对象:

 "transactiedatum": "23-02-1993"

but instead, im getting: 但相反,我得到:

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

First of all, its unix time format, second, there is change in the json structure. 首先,它的unix时间格式,第二,json结构有变化。 How can I handle this? 我怎么处理这个?

We had similar problem. 我们有类似的问题。 This sounds complicated, but its not that kind of big of a deal. 这听起来很复杂,但它不是那么大的交易。

So, first of all, here is the link to Mongo C# drive on github: MongoC#Driver 所以,首先,这里是github上Mongo C#驱动器的链接: MongoC#Driver

For you, these are 2 important links in there: 对你来说,这里有两个重要的链接:

  1. Bson Extension Methods Bson扩展方法
  2. JsonWriter JsonWriter
  3. JsonWriterContext JsonWriterContext

What we wanted to achieve is that we don't want representation in our Json string to be in unix timestamp format, so we copied these classes into our project with different names, so, here are all of them: 我们想要实现的是我们不希望我们的Json字符串中的表示形式采用unix时间戳格式,因此我们将这些类复制到具有不同名称的项目中,因此,以下是所有这些:

Extension Class: 扩展类:

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();
                }
            }
        }
    }

So basicaly, copy the whole class from github into your own class, and change names of 2 methods: ToJson() into one of yours. 所以基本上,将整个类从github复制到你自己的类中,并将2个方法的名称:ToJson()更改为你的一个。 Over here you can see that mine are ToJsonMine(). 在这里你可以看到我的是ToJsonMine()。

Now, to the second class you will need: 现在,您将需要第二节课:

JsonWriter 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();
    }

    }
}

This is where the magic happens. 这就是魔术发生的地方。 Copy the whole class JsonWriter from GitHub into your own and give it a new name(Extend BsonWriter nad implement all methods). 将整个类JsonWriter从GitHub复制到您自己的类中,并为其命名(Extend BsonWriter nad实现所有方法)。 Now, here you can manipulate how do you want your date to be serialized. 现在,您可以在这里操纵您希望如何序列化日期。 Change WriteDateTime(long value) accordingly. 相应地更改WriteDateTime(long value) As you can see, in the case JsonOutputMode.Strict: I changed it to return me a DateTime object formatted the way I need it. 正如您所看到的,在case JsonOutputMode.Strict:case JsonOutputMode.Strict:我更改了它,以我需要的方式返回一个DateTime对象。

And lastly, since MongoSerializer has the internal class that is called JsonWriterContext , you need to create your own and use it in JsonWriter (step 2). 最后,由于MongoSerializer具有名为JsonWriterContext的内部类,因此您需要创建自己的类并在JsonWriter使用它(步骤2)。

This is how it looks with me(you can copy it whole): 这就是我的样子(你可以整个复制):

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; }
        }
    }
}

After you have everything, you will see in the MongoCursorJsonConverter(1st step), in the second ToJsonMine() method that I have this line: 拥有所有内容后,您将在MongoCursorJsonConverter(第1步)中看到,在第二个ToJsonMine()方法中,我有这一行:

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

You should just replace it with your own custom class that you created in step 2 and it will work like a charm. 您应该将它替换为您在步骤2中创建的自定义类,它将像魅力一样工作。

And in the end, you just call: 最后,你只需致电:

var lists = mongoListBatch.ToJson(settings);

and it will serialize date like you added inside WriteDate(long value) 它会像你在WriteDate(long value)添加的那样序列化日期WriteDate(long value)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM