1

I have an object I am attempting to deserialize with Newtonsoft.Json but it's giving me trouble due to properties containing dashes. The event-data property has a dash for example.

{
    "signature": {
        "timestamp": "3421342",
        "token": "88f79ede5e9af44d6a2",
        "signature": "a57233ab698324dbf1ca9dff"
    },
    "event-data": { ... }
}

I don't have control over the BaseEvent model I am deserializing to but I did extend it to MyEvent to add some custom code for other stuff. So I am unable to decorate [JsonProperty] on properties. So I need to do this using either a contract resolver or some other more global method but ideally localized to just this model (an attribute decorator of some sort).

I was able to add this KebabCaseNamingStrategy decorator on my model which appears to be exactly what I need but it didn't do anything until I used the new keyword to hide the base class member. Then EventData gets deserialized (although the child properties on it containing dashes are not deserialized).

[JsonObject(NamingStrategyType = typeof(KebabCaseNamingStrategy))]
public class MyEvent : BaseEvent
{
   public new EventDataObject EventData { get; set; }
}
Adam
  • 4,590
  • 10
  • 51
  • 84
  • `[JsonObject(NamingStrategyType = typeof(KebabCaseNamingStrategy))]` only applies to properties declared by that type. It (apparently) doesn't apply to base class properties, and definitely doesn't recursively to properties of referenced objects in the serialization graph. – dbc Aug 10 '21 at 00:02
  • To change naming strategy for an object and all nested objects, see [JSON .NET Custom Name Resolver for Sub-Properties](https://stackoverflow.com/q/40597532/3744182). You may need to create your own `KebabCaseContractResolver` to use the accepted answer as-is. Or you could enhance it to add an second constructor for `AlternateContractResolverConverter` that takes a naming strategy type. Does that answer your question sufficiently? – dbc Aug 10 '21 at 00:06
  • I tried inheriting the `DefaultContractResolver` to create a `KebabCaseContractResolver` but the entire object is null when deserialized as shown here: https://dotnetfiddle.net/8T4osw – Adam Aug 10 '21 at 16:12
  • I'm really surprised they have a naming strategy already in the core library but no way to easily decorate an object to respect kebab case – Adam Aug 10 '21 at 16:13
  • The basic idea is that Json.NET defines a contract for each type, then serializes according to that contract. You are expecting an attribute applied to a derived class to change the contract for base class properties. Opinions could differ on whether that is actually desirable. – dbc Aug 10 '21 at 16:25
  • Fair enough. So I guess my only option is to pull the type into my code. The whole point of this library was to provide the type but seems sort of useless without a bunch of mapping code laying around somewhere. I'd rather have it directly specified on the model how these properties should be handled. – Adam Aug 10 '21 at 16:35
  • The correct usage would be `[JsonConverter(typeof(AlternateContractResolverConverter), typeof(KebabCaseContractResolver))]` not `[JsonConverter(typeof(KebabCaseContractResolver))]` because a contract resolver is not a converter. But it turns out that `AlternateContractResolverConverter` had a bug or limitation making it not work when applied to a type instead of a property. You can see a fixed version here: https://dotnetfiddle.net/Q8kDw2. Does that answer your question? – dbc Aug 10 '21 at 17:10

0 Answers0