Fork me on GitHub

Serializing with Newtonsoft.Json Edit on GitHub


The default JSON serialization strategy inside of Marten uses Newtonsoft.Json. We have standardized on Newtonsoft.Json because of its flexibility and ability to handle polymorphism within child collections. Marten also uses Newtonsoft.Json internally to do JSON diff's for the automatic dirty checking option.

Out of the box, Marten uses this configuration for Newtonsoft.Json:


private readonly JsonSerializer _serializer = new JsonSerializer
{
    TypeNameHandling = TypeNameHandling.Auto,

    // ISO 8601 formatting of DateTime's is mandatory
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead
};

To customize the Newtonsoft.Json serialization, you need to explicitly supply an instance of Marten's JsonNetSerializer as shown below:


var serializer = new Marten.Services.JsonNetSerializer();
        
// To change the enum storage policy to store Enum's as strings:
serializer.EnumStorage = EnumStorage.AsString;

// All other customizations:
serializer.Customize(_ =>
{
    // Code directly against a Newtonsoft.Json JsonSerializer
    _.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
    _.ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor;
});

var store = DocumentStore.For(_ =>
{
    _.Connection("some connection string");

    // Replace the default JsonNetSerializer with the one we configured
    // above
    _.Serializer(serializer);
});
You should not override the Newtonsoft.Json ContractResolver with CamelCasePropertyNamesContractResolver for Json Serialization. Newtonsoft.Json by default respects the casing used in property / field names which is typically PascalCase. This can be overriden to serialize the names to camelCase and Marten will store the JSON in the database as specified by the Newtonsoft.Json settings. However, Marten uses the property / field names casing for its SQL queries and queries are case sensitive and as such, querying will not work correctly.
Marten actually has to keep two Newtonsoft.Json serializers, with one being a "clean" Json serializer that omits all Type metadata. The need for two serializers is why the customization is done with a nested closure so that the same configuration is always applied to both internal JsonSerializer's.