当类型是使用MongoDB的csharp的驱动程序中更改反序列化领域(Deserializing f

2019-07-28 22:51发布

我测试了一些与MongoDB的场景,看看如何从可能的数据问题恢复。

我与它最初是投字符串地址邮编属性类(与地址的集合地址)。 我救出来的地址多条记录,并可以检索它们无一不精。 像这样,VAR = allAddresses addresses.FindAllAs();

我改变了邮政编码属性为int和保存的一些记录。 然后我改变了邮政编码财产回字符串。

当我尝试读回我得到一个错误反序列化,符合市场预期。 VAR allAddresses = addresses.FindAllAs();

我的目标是能够所以如果发生反序列化领域的错误,我可以选择忽略它或将默认值来覆盖反序列化。

我已经尝试了自定义序列,这是行不通的。 任何建议,将不胜感激。

public class MyCustomSerializer : BsonBaseSerializer
  {

    public override object Deserialize(BsonReader bsonReader, Type nominalType,  IBsonSerializationOptions options)
    {
      if (bsonReader.CurrentBsonType != BsonType.String)
      {
        return string.Empty;
      }

      return bsonReader.ReadString();
    }

    public override void Serialize(
               BsonWriter bsonWriter,
               Type nominalType,
               object value,
               IBsonSerializationOptions options)
    {
      bsonWriter.WriteStartDocument();
      bsonWriter.WriteName("ZipCode");
      bsonWriter.WriteString(value.ToString());
      bsonWriter.WriteEndDocument();
    }
  }

Answer 1:

有一个正在进行几件事情。 最主要的是,你必须要消耗输入,无论类型或反序列化过程变得不同步的。 我测试过你的情况写称为ZipCodeSerializer自定义序列它处理空值和作为字符串写入邮编,但接受输入字符串或整数和整数转换成字符串。

我用这个类来测试:

public class Address
{
    public ObjectId Id;
    public string ZipCode;
}

这是我写的自定义序列:

public class ZipCodeSerializer : BsonBaseSerializer
{
    public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
    {
        var bsonType = bsonReader.CurrentBsonType;
        switch (bsonType)
        {
            case BsonType.Null:
                bsonReader.ReadNull();
                return null;
            case BsonType.String:
                return bsonReader.ReadString();
            case BsonType.Int32:
                return bsonReader.ReadInt32().ToString();
            default:
                var message = string.Format("ZipCodeSerializer expects to find a String or an Int32, not a {0}.", bsonType);
                throw new BsonSerializationException(message);
        }
    }

    public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
    {
        if (value == null)
        {
            bsonWriter.WriteNull();
        }
        else
        {
            bsonWriter.WriteString((string)value);
        }
    }
}

你必须确保自定义序列挂起来,你可以这样做:

BsonClassMap.RegisterClassMap<Address>(cm =>
    {
        cm.AutoMap();
        cm.GetMemberMap(a => a.ZipCode).SetSerializer(new ZipCodeSerializer());
    });

所以,现在的地址类的邮编字段将通过自定义序列化处理。

我用BsonDocument可以很容易迫使在我的测试收集的数据的存储的特定版本中创建一些测试数据:

collection.Drop();
collection.Insert(new BsonDocument());
collection.Insert(new BsonDocument("ZipCode", BsonNull.Value));
collection.Insert(new BsonDocument("ZipCode", "12345"));
collection.Insert(new BsonDocument("ZipCode", 56789));

下面介绍一下文件看起来像使用蒙戈外壳:

> db.test.find()
{ "_id" : ObjectId("4f871374e447ad238040e346") }
{ "_id" : ObjectId("4f871374e447ad238040e347"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e348"), "ZipCode" : "12345" }
{ "_id" : ObjectId("4f871374e447ad238040e349"), "ZipCode" : 56789 }
>

所以我们看到,一些邮编是字符串,有些是整数(也有抛出空)。

这是我的测试代码:

foreach (var document in collection.FindAll())
{
    Console.WriteLine(document.ToJson());
}

并运行测试代码的输出是:

{ "_id" : ObjectId("4f871374e447ad238040e346"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e347"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e348"), "ZipCode" : "12345" }
{ "_id" : ObjectId("4f871374e447ad238040e349"), "ZipCode" : "56789" }
Press Enter to continue

请注意,这是在数据库中int邮编现在是一个字符串。

我的测试程序的完整的源代码,请访问:

http://www.pastie.org/3775465



文章来源: Deserializing field when type is changed using MongoDb csharp driver