Json. Net Contractresolver Vs. Jsonconverter
I've Been Working with Json. Net for a While. I Have Written Both Custom Converters and Custom Contract Resolvers (Generally from Modifying Examples on S. O...
I've been working with JSON.net for a while. I have written both custom converters and custom contract resolvers (generally from modifying examples on S.O. and the Newtonsoft website), and they work fine.
The challenge is, other than examples, I see little explanation as to when I should use one or the other (or both) for processing. Through my own experience, I've basically determined that contract resolvers are simpler, so if I can do what I need with them, I go that way; otherwise, I use custom JsonConverters. But, I further know both are sometimes used together, so the concepts get further opaque.
Questions:
- Is there a source that distinguishes when to user one vs. the other? I find the Newtonsoft documentation unclear as to how the two are differentiated or when to use one or the other.
- What is the pipeline of ordering between the two?
1 Answer
Great question. I haven't seen a clear piece of documentation that says when you should prefer to write a custom ContractResolver or a custom JsonConverter to solve a particular type of problem. They really do different things, but there is some overlap between what kinds of problems can be solved by each. I've written a fair number of each while answering questions on StackOverflow, so the picture has become a little more clear to me over time. Below is my take on it.
ContractResolver
A contract resolver is always used by Json.Net, and governs serialization / deserialization behavior at a broad level. If there is not a custom resolver provided in the settings, then the DefaultContractResolver is used. The resolver is responsible for determining:
- what contract each type has (i.e. is it a primitive, array/list, dictionary, dynamic,
JObject, plain old object, etc.); - what properties are on the type (if any) and what are their names, types and accessibility;
- what attributes have been applied (e.g.
[JsonProperty],[JsonIgnore],[JsonConverter], etc.), and - how those attributes should affect the (de)serialization of each property (or class).
Generally speaking, if you want to customize some aspect of serialization or deserialization across a wide range of classes, you will probably need to use a ContractResolver to do it. Here are some examples of things you can customize using a ContractResolver:
- Change the contract used for a type
- Change the casing of property names when serializing
- Programmatically apply attributes to properties without having to modify the classes (particularly useful if you don't control the source of said classes)
- Programmatically unapply (ignore) attributes that are applied to certain classes
- Conditionally serialize properties
- Introduce custom attributes and apply some custom behavior based on those attributes