我在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结构有变化。我怎么处理这个?
答案 0 :(得分:1)
我们遇到了类似的问题。这听起来很复杂,但这并不是什么大不了的事。
首先,这里是github上Mongo C#驱动的链接: MongoC#Driver
对你而言,这些是其中的两个重要链接:
我们想要实现的是我们不希望我们的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)