-4

Should I consider contract resolver if I am using custom json converter?

I experienced an issue when contract resolver is never called due to own json converter...

If I should do that.. then what is common way to do that? I cannot find any information about that...

Taryn
  • 242,637
  • 56
  • 362
  • 405
Maxim
  • 13,029
  • 6
  • 30
  • 45
  • Without a [mcve] we can't really help you. Just to guess, if your problem is that hardcoding of names in a `JsonConverter` conflicts with name mapping in a `ContractResolver`, you could 1) Loop through the properties returned by `serializer.ContractResolver.ResolveContract(objectType).Properties` and check either [`JsonProperty.UnderlyingName`](http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_UnderlyingName.htm) or [`PropertyName`](http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_PropertyName.htm) as appropriate, or – dbc Jul 24 '17 at 19:06
  • .. 2) Use [`JsonSerializer.Populate()`](http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_JsonSerializer_Populate.htm) to populate members for which you want default deserialization as shown e.g. in [this answer](https://stackoverflow.com/a/41512702/3744182). – dbc Jul 24 '17 at 19:07
  • It is nice idea: "serializer.ContractResolver.ResolveContract(objectType).Prop‌​erties". But it does not work in my specific case... I am reading json to dynamic, so objectType is System.Object which does not have properties. I guess ResolveContract is the way how James planned it to be used.. but it looks it is not possible if you want to have very custom logic in data converter. I will investigate it further. – Maxim Jul 24 '17 at 19:45
  • If you're talking about [renaming of dictionary keys](https://stackoverflow.com/q/24143149/3744182), then Json.NET only does that during serialization, **not deserialization**. See [here](https://github.com/JamesNK/Newtonsoft.Json/issues/391) for confirmation. That issue is old, but notice that [`NamingStrategy`](http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_NamingStrategy.htm) has `GetDictionaryKey()` but no corresponding `ReverseGetDictionaryKey()` for deserialization. – dbc Jul 24 '17 at 19:56
  • But I am already do that during deserialization... I mean renaming from camel case to pascal case (replacing keys if I understand you correctly)... In addition I create ExpandoObject (used with dynamic in controller). All that is made in JsonConverter. But what I am not doing: I do not consider options of ContractResolver during this deserialization. And it is what I want to solve... But since dynamic is represented as object I do not have properties here: serializer.ContractResolver.ResolveContract(objectType).Pro‌​p‌​erties... So when my converter is used any resolver is ignored.. bad... – Maxim Jul 24 '17 at 20:06
  • So should I (or even can) access ContractResolver to apply its rules in json converter? Let's say I want to call ResolvePropertyName(string propertyName) to apply specified logic (what is now impossible.. it is protected). – Maxim Jul 24 '17 at 20:21
  • `ResolvePropertyName()` is protected but Newtonsoft is migrating non-type-specific logic for mapping of names to `NamingStrategy`, so you could just call [`DefaultContractResolver.NamingStrategy?.GetPropertyName(name) ?? name`](http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_NamingStrategy_GetPropertyName.htm), all of which are public. Still I'd need to see a [mcve] to be sure that would work. – dbc Jul 24 '17 at 20:28
  • I cannot add any example because I cannot address this issue to some small piece of code. Ask yourself what it can be? I personally do not know. But we can say it is any code inside: ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer). Also I am worrying about such migration. What is about CreateProperties? It allows us to filter properties. Also why DefaultContractResolver? I think it should be something in "serializer.ContractResolver" as you mentioned originally. Of course it is IContractResolver, and cast to "DefaultContractResolver" can be unsafe. – Maxim Jul 24 '17 at 20:47

1 Answers1

0

From documentation

Passing a JsonConverter to SerializeObject or DeserializeObject provides a simple way to completely change how an object is serialized. There is, however, a small amount of overhead; the CanConvert method is called for every value to check whether serialization should be handled by that JsonConverter. There are a couple of ways to continue to use JsonConverters without any overhead. The simplest way is to specify the JsonConverter using the JsonConverterAttribute. This attribute tells the serializer to always use that converter when serializing and deserializing the type, without the check.

But

If the class you want to convert isn't your own and you're unable to use an attribute, a JsonConverter can still be used by creating your own IContractResolver.

Ivan R.
  • 1,875
  • 1
  • 13
  • 11
  • I am asking how custom JsonConverter is interacting with existing (or custom) ContractResolver. I am not about attributes.. I can specify JsonConverter globally as well. In other words how it should be implemented if we have both (converter and resolver)? – Maxim Jul 24 '17 at 17:41
  • Let's say you have some type which can represented as Dictionary. And you use own json converter to do that. But in addition you have contract resolver which should for example change case of property name. This contract resolver will never be applied. So how to consider that resolver in such json converter? – Maxim Jul 24 '17 at 17:45