10

Prehistory: I have a class hierarchy (a big one) which was generated from an XML schema (XSD).

MyObj obj;

Nowadays: I need to parse a string value, which is actually an XML to an object using the generated class hierarchy and then I need to put the object into MongoDB. The code is:

private BsonDocument XmlToBson(string content)
{
    MyObj obj;
    using (var reader = new StringReader(content))
    {
        var serializer = new XmlSerializer(typeof(MyObj));
        obj = (MyObj) serializer.Deserialize(reader);
    }

    return obj.ToBsonDocument();
}

The problem: I have a lot of null children objects in the hierarchy, it looks like this in Robomongo:

Object which is null is added

I want to avoid adding null objects into the database. I know I can ignore them one by one, like described here Ignoring Default Values by using attributes or lambda expressions. But because the hierarchy is big and complex I do not like this approach. I am to lazy to list all the properties which have to be ignored when they have null values. Even more, the class can be regenerated in future and it will be a nightmare to support the list of properties which have to be ignored.

Question: How can I achieve the goal and ignore the null values globally no matter where the object is in hierarchy? I am working with MongoDB C# driver ver. 2.2.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Antipod
  • 1,593
  • 3
  • 23
  • 43
  • Hey Antipod, ignoring them will be difficult if they exist and you're not removing them by a `null` value check. What do you mean by "ignore" btw, as in not insert them or insert another object if it's null into the column as a "placeholder"? – Nick Bull Aug 03 '16 at 15:31
  • By "ignore" I mean I do not want to see them in the database. Put fake values, i.e. values which will not be used, does not sound as a good idea, I do not want to have trash in the database. And checking if something is null (how?) and remove it sounds like an overhead or probably I do not understand what you mean. – Antipod Aug 03 '16 at 15:38
  • See http://stackoverflow.com/a/43259080/194717 – Tony Apr 06 '17 at 15:11

3 Answers3

17

You can apply the effects of most attributes to all properties while serializing by registering convention packs.

Below the IgnoreIfNullConvention is registered, implicitly applying the [IgnoreIfNull] attribute to all properties while serializing and deserializing.

var anon = new
{
    Foo = "bar",
    Baz = (string)null,
};

ConventionRegistry.Register("Ignore", 
                            new ConventionPack 
                            { 
                                new IgnoreIfNullConvention(true) 
                            }, 
                            t => true);

var bsonDocument = anon.ToBsonDocument();

This will yield a document only containing the Foo key.

When desired, you can also Remove() this convention pack by name after serialization.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
6

You can also apply the [BsonIgnoreIfNull] attribute from the MongoDB.Bson.Serialization.Attributes
namespace to a class field if you don't what that field with a null value to appear in the BSON Document.

public class Person
{
    public string Name { get; set; }

    [BsonIgnoreIfNull]
    public List<string> Children { get; set; }
}
Anthony Liriano
  • 589
  • 1
  • 7
  • 16
6

Actually, using IgnoreIfDefaultConvention can cause an unintended behavior due the fact it affects all default values. For instance, values as the list above will not be saved:

  • int = 0
  • decimal = 0
  • bool = false

If you want to ignore only null values, the best approach is IgnoreIfNullConvention.

Here is an example of it:

ConventionRegistry.Register("IgnoreIfNullConvention", new ConventionPack { new IgnoreIfNullConvention(true) }, t => true);
Rafael Jusi
  • 61
  • 1
  • 2