11

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.

3
  • 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"? Commented Aug 3, 2016 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. Commented Aug 3, 2016 at 15:38
  • See stackoverflow.com/a/43259080/194717 Commented Apr 6, 2017 at 15:11

3 Answers 3

18

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is very elegant, wish I'd known about this for a long time!
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; }
}

Comments

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

1 Comment

this brings another problem, what if we need to ignore empty arrays and null values but not the int decimal bool?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.