Marten: Patch API does not respect "TypeNameHandling" when serializing nested objects

Created on 25 Jan 2019  路  9Comments  路  Source: JasperFx/marten

When setting custom serializing settings below, the patch api calls fail to set the $type property.

var serializer = new JsonNetSerializer();
serializer.Customize(config =>
{
    config.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects;
});

I've noticed that TypeNameHandling is hardcode to TypeNameHandling.None in JsonNetSerializer seen below. When the patch dictionary gets serialized with this setting, it will prevent the inner object from storing its type information.

https://github.com/JasperFx/marten/blob/eb079897138c62d5d765323769e000d27d9c1667/src/Marten/Services/JsonNetSerializer.cs#L33-L39

bug

All 9 comments

@psmith6 I don't think Patch is every going to play nicely with any TypeNameHandling strategy other than None. The Patch functionality actually uses Javascript at the moment, and knows absolutely nothing about Newtonsoft functionality

I hit this problem a few months back too, and am getting back round to looking at it now.

Workaround I see:

  • Don't use the patch API for interface types
  • Rather than trying to control the serialisation, customise the deserialisation by using a custom JsonConverter (I presume these can be used). Obviously a PITA if you have a lot of types

@jeremydmiller Marten already supports querying for raw JSON - what are your thoughts on extending the Patch API to support setting raw JSON? This would allow full control over serialisation, and might also be useful in cases where you already have JSON and want to avoid an extra serialisation/deserialisation?

@cocowalla That sound reasonable for me. It's similar case as for giving users ability to pass custom sql for orderby. That gives user possibility to do customisation even if we don't support this case yet in Marten.

For info, I tried out the JsonConverter option, and it does work as expected. It works for my use case, but obviously it's not a great solution if you have a lot of types to create a converter for.

@cocowalla Getting back into things this week.

"@jeremydmiller Marten already supports querying for raw JSON - what are your thoughts on extending the Patch API to support setting raw JSON?" -- that's basically what it does today, or am I missing something?

Some new thoughts on this one today:

  • It looks like it's possible to not use the "clean" serializer when appending items
  • The patching is going to have to be smart enough to "know" when an item is being appended that would force Newtonsoft to use the $type, or "know" that the type handling is set to do so.

This is going back a bit, but I think what I meant was allowing the developer to pass a JSON string as the value, instead of relying on Marten to serialise a C# object as wanted. There are some footguns here, but I don't see devs wanting to use this unless they had a genuine reason (like controlling serialisation).

@cocowalla I really don't want to have to support that, unless it's an "UnsafeReplaceJson()" kind of signature:)

Some of this could be pushed toward a Javascript patching model. I actually meant to add that at one point where you could revert to Javascript to do patching operations that aren't supported by the patching api. So you could have an arbitrary number of args to use in a JS mutator.

For tomorrow, the way this is going to get fixed is to:

  • [x] ISerializer needs a new ToJsonWithTypeInformation(object) method
  • [x] The patching operation needs to be smart enough to "know" when to opt into this. Think that would be non-simple items in a collection, and knowing that the actual element does not match the declared item type
Was this page helpful?
0 / 5 - 0 ratings

Related issues

jinhong- picture jinhong-  路  7Comments

gcox picture gcox  路  3Comments

jeremydmiller picture jeremydmiller  路  6Comments

jokokko picture jokokko  路  9Comments

jeremydmiller picture jeremydmiller  路  7Comments