【问题标题】:Handling MongoDB's ISODate() when attempting to parse a serialized JSON string尝试解析序列化 JSON 字符串时处理 MongoDB ISO Date()
【发布时间】:2014-02-23 08:14:42
【问题描述】:

我正在通过带有 ASP.NET MVC 网站的官方 C# 驱动程序使用 MongoDB。

我有以下 C# 模型:

public class Contact
{
    public ObjectId Id { get; set; }
    public string Name { get; set; }
    public DateTime DateAdded { get; set; }
}

当从 MongoDB 中提取并通过 MVC 序列化为 JSON 字符串时,如下所示:

{
    "_id"  : ObjectId("52eaad4839b60812fca4bf28"),
    "Name": "Joe Blow",
    "DateAdded" : ISODate("2014-01-30T19:51:35.977Z")
}

当我尝试通过 JSON.parse() 将其从 JSON 字符串转换为浏览器上的 Javascript 对象时,我收到以下错误:

Uncaught SyntaxError: Unexpected token I

这是因为ISODate(...) 不是有效的 JSON

ObjectId() 也不是有效的 JSON,但我处理它的方式是在客户端上解析 JSON 字符串之前简单地执行 string.replace()。我考虑过为ISODate() 做同样的事情,但感觉有点太老套了。

有没有什么我可以在客户端不使用正则表达式的情况下做的?也许来自 MongoDB 驱动程序?

【问题讨论】:

  • 您也有ObjectId(...) 的问题,而不仅仅是ISODate。这不是一个有效的 json。
  • 我在解析之前从字符串中删除ObjectId(),留下封装的 GUID。
  • 那么对ISODate做同样的事情,例如,Json.net 可以处理剩下的事情。
  • 能否在解析前添加一个名为 ISODate 的全局函数?

标签: c# asp.net-mvc json mongodb knockout.js


【解决方案1】:

我认为您需要进一步调整 JSON 序列化程序。试试这个:

var jsonWriterSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict };
Console.WriteLine(document.ToJson(jsonWriterSettings));

【讨论】:

  • 这正是我想要的。我更喜欢生成的 JSON 不需要在客户端上进行按摩。谢谢!
  • 它可以产生“有效”的 JSON,但它会产生一些非常糟糕的值。日期变成 {输入:{ $date: 190012312211 } },典型的应用程序将很难做一些有用的事情。自定义 JSON.NET 转换器可以解决这个问题,但仍然可以。如果 JsonOutputMode 真的很好。 Strict 可以生成“标准”Json。
【解决方案2】:

您应该使用JsonConvert 将日期正确地转换为 Json。接受的答案会产生一个日期对象,例如:@Rick Strahl 提到的{ $date: 190012312211 }。这应该有效:

object val = BsonTypeMapper.MapToDotNetValue(bsonDocument);
string jsonString = JsonConvert.SerializeObject(val);

【讨论】:

  • 如果你的 bsonDocument 是一个列表呢?
【解决方案3】:

如果 JSON 数据对于 eval 是安全的(因为它可能来自您的服务器),那么您可以这样做。它不是特别漂亮,但它完成了工作。

http://jsfiddle.net/CVLhx/

var str = '{"_id"  : ObjectId("52eaad4839b60812fca4bf28"),"Name": "Joe Blow","DateAdded" : ISODate("2014-01-30T19:51:35.977Z")}';

function ObjectId(id) { return id;}
function ISODate(d) {return d;}

var obj = eval('(' + str + ')');
console.log(obj);

【讨论】:

  • 这适用于 JavaScript,但问题是用 C# 标记的。
【解决方案4】:

正如@Louie Almeda 所建议的,我认为最好的方法是使用 BsonTypeMapper.MapToDotNetValue。 BsonTypeMapperOptions 也可以自定义。

这是我使用 LINQ 和 newtonsoft 序列化程序将 BsonDocument 上的列表转换为 json 字符串的方法:

var jsonString = JsonConvert.SerializeObject(bsonDocuments.ConvertAll(d => BsonTypeMapper.MapToDotNetValue(d)), Formatting.Indented)

【讨论】:

    【解决方案5】:

    我意识到我参加这个聚会很晚了,但无论如何我都会发布一个答案,以防其他人过来寻找解决方案(就像我一样)。

    诀窍是让 Mongo db 驱动程序进行反序列化:

    var collection = database.GetCollection<Contact>("collection name");
    var contact = collection.Find(Query.EQ("Name", "Joe Blow"));
    

    现在contact 将具有预期值。

    【讨论】:

      【解决方案6】:
       var IDict = v as IDictionary<string, object>;
                              var dict = IDict.ToDictionary(x => x.Key, x => x.Value);
                              var dateVal = dict["$date"];
                              var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                              var dateTimeVal = epoch.AddMilliseconds(Convert.ToDouble(dateVal));
      

      【讨论】:

        猜你喜欢
        • 2014-02-23
        • 1970-01-01
        • 1970-01-01
        • 2012-10-04
        • 2016-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-22
        相关资源
        最近更新 更多