Change default member serialization mode to MemberSerialization.Fields - json.net

I would like to change the default serialization mode in Json.NET from MemberSerialization.OptOut to MemberSerialization.Fields without needing to scatter [JsonObject(MemberSerialization.Fields)] attributes through every class in my code base.
My primary reasons for wanting this is to get my Json deserializer to not call constructors and to make sure that all fields, including private ones, are correctly serialized and deserialized.
An example of the behaviour I'm looking for would be the serialization / deserialization behaviour of the BinaryFormatter, except without needing to scatter [Serializable] attributes through the entire codebase.

Related

Why does [Serializable] cause Newtonsoft.Json serializer to include backing fields?

If I have [Serializable] attribute on a class then it causes the resulting serialised Json string to include backing members created by the framework.
For example I get below for my Id field:
<Id>k__BackingField=20001
I could find many resources on SOF and elsewhere to get around this problem but I couldn't find why Json serializer is behaving differently when it sees [Serializable] attribute.
If the Jason serializer doesn't serialise members and only serialise properties then why does it behave differently when a class is decorated with [Serializable] attribute?
Please note I'm not looking for a way to fix this issue as I have already found that. I would like to know why Newtonsoft.Jsonserialiser behaves differently here.
In case someone wants to find the reason in the future, following explains how objects are serialised by Json.Net:
Breakdown of Type Serialization > Objects
By default a type's properties are serialized in opt-out mode. What
that means is that all public fields and properties with getters are
automatically serialized to JSON, and fields and properties that
shouldn't be serialized are opted-out by placing JsonIgnoreAttribute
on them. To serialize private members, the JsonPropertyAttribute can
be placed on private fields and properties.
Types can also be serialized using opt-in mode. Only properties and
fields that have a JsonPropertyAttribute or DataMemberAttribute on
them will be serialized. Opt-in mode for an object is specified by
placing the JsonObjectAttribute or DataContractAttribute on the type.
Finally, types can be serialized using a fields mode. All fields, both
public and private, are serialized and properties are ignored. This
can be specified by setting MemberSerialization.Fields on a type with
the JsonObjectAttribute or by using the .NET SerializableAttribute and
setting IgnoreSerializableAttribute on DefaultContractResolver to
false.

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. 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?
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
Serialize all Dictionaries as an Array of Key/Value Pairs
Serialize ListItems as a regular object instead of string
Change the casing of property names when serializing
Use camel case for all property names
Camel case all property names except dictionaries
Programmatically apply attributes to properties without having to modify the classes (particularly useful if you don't control the source of said classes)
Globally use a JsonConverter on a class without the attribute
Remap properties to different names defined at runtime
Allow deserializing to public properties with non-public setters
Programmatically unapply (ignore) attributes that are applied to certain classes
Optionally turn off the JsonIgnore attribute at runtime
Make properties which are marked as required (for SOAP) not required for JSON
Conditionally serialize properties
Ignore read-only properties across all classes
Skip serializing properties that throw exceptions
Introduce custom attributes and apply some custom behavior based on those attributes
Encrypt specially marked string properties in any class
Selectively escape HTML in strings during deserialization
JsonConverter
In contrast to a ContractResolver, the focus of a JsonConverter is more narrow: it is really intended to handle serialization or deserialization for a single type or a small subset of related types. Also, it works at a lower level than a resolver does. When a converter is given responsibility for a type, it has complete control over how the JSON is read or written for that type: it directly uses JsonReader and JsonWriter classes to do its job. In other words, it can change the shape of the JSON for that type. At the same time, a converter is decoupled from the "big picture" and does not have access to contextual information such as the parent of the object being (de)serialized or the property attributes that were used with it. Here are some examples of problems you can solve with a JsonConverter:
Handle object instantiation issues on deserialization
Deserialize to an interface, using information in the JSON to decide which concrete class to instantiate
Deserialize JSON that is sometimes a single object and sometimes an array of objects
Deserialize JSON that can either be an array or a nested array
Skip unwanted items when deserializing from an array of mixed types
Deserialize to an object that lacks a default constructor
Change how values are formatted or interpretted
Serialize decimal values as localized strings
Convert decimal.MinValue to an empty string and back (for use with a legacy system)
Serialize dates with multiple different formats
Ignore UTC offsets when deserializing dates
Make Json.Net call ToString() when serializing a type
Translate between differing JSON and object structures
Deserialize a nested array of mixed values into a list of items
Deserialize an array of objects with varying names
Serialize/deserialize a custom dictionary with complex keys
Serialize a custom IEnumerable collection as a dictionary
Flatten a nested JSON structure into a simpler object structure
Expand a simple object structure into a more complicated JSON structure
Serialize a list of objects as a list of IDs only
Deserialize a JSON list of objects containing GUIDs to a list of GUIDs
Work around issues (de)serializing specific .NET types
Serializing System.Net.IPAddress throws an exception
Problems deserializing Microsoft.Xna.Framework.Rectangle

Change default GUID serialization format

By default, the JSON and XML serializers in Web API 2 just call ToString() to serialize out a Guid, which means it includes dashes: fd190000-5532-8477-e053-9a16ce0af828. I'd really like to change the default serialization to the format returned by ToString("N"), which does not include dashes: fd19000055328477e0539a16ce0af828.
I found this article on creating a JsonConverter and overriding the WriteJson() method to use ToString("N"). That worked fine for JSON, but I haven't found anything similar for XML serialization.
Is there a way to implement this only once, regardless of how many MediaTypeFormatters are present? If not, how can I override XML serialization as well?

What are the downsides of "typing" your control state?

I am relatively new to Web Parts and Web Forms (I have only worked a lot with the MVC framework).
I am planning to store some data in the control state. All the examples I can find put an object[] array in the control state and the base control state on the 0 index.
I don't really like putting everything in an object[], so I wanted to create an extra class for my web part with typed properties: e.g. MyWebPartControlState. I will store the base control state in a property BaseControlState of type object.
I was wondering if this could cause any problems or if there are any other reasons why this might not be a good idea. I am wondering because it feels logical to me, but I cannot find any examples of control state where they don't put everything in the control state directly or in a object[].
Thanks in advance.
The control state is persisted in the same field as view state and follows the same rules for serialization. All the samples you found use an object array because that's one of the types the optimized state serializer in ASP.NET understands and for which is able to optimize serialization.
If you use a custom object the serializer won't use the optimizations and instead will serialize your object using the BinaryFormatter which will lead to bloated control state. If you want to have a strongly typed view of your state you should implement IStateManager on your custom class so that it encapsulates the transformation of itself from and to simple objects that the serializer understands.
If I recall correctly the serializer can efficiently serialize the following types:
Primitive types (int, long, etc);
DateTime;
string;
Boxed values of supported value types;
Object arrays containing instances of supported types;
Pair and Triplet objects containing instances of supported types.
I wrote a short blogpost illustrating the differences in size resulting from a simple custom class being serialized with BinaryFormatter versus implementing IStateManager and decomposing to simple types that the serializer can optimize. You can find it at:
ASP.NET ViewState Tips and Tricks #2

ASP.NET ScriptService prevent return of null properties in JSON

Basically I want to make my script service only serialise properties that are not null on an array of object I am returning... So this..
{"k":"9wjH38dKw823","s":10,"f":null,"l":null,"j":null,"p":null,"z":null,"i":null,"c":null,"m":0,"t":-1,"u":2}
would be
{"k":"9wjH38dKw823","s":10,"m":0,"t":-1,"u":2}
Does anyone know if this is possible?
Basically the reason for this is because null values are for unchanged properties. A local copy is kept in the javascript that is just updated to reduce traffic to the server. Change values are then merged.
You can create a custom JavaScriptConverter class for the JSON serialization process to use to handle your object, and then put the necessary logic in the Serialize method of that class to exclude the properties that are null.
This article has a clear step-by-step discussion of the process involved in creating it.
You probably would not need to actually implement the Deserialize method (can throw a NotImplementedException) if you are not passing that type of object in as an input parameter to your web services.

Resources