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?
Related
I automatically generate schema for my classes using Json.NET Schema and it works great for validation. I wanted to add the ability for my classes to provide snippets directly and emit them into a (presumably separate) schema file, for use in Visual Studio Code.
https://code.visualstudio.com/docs/languages/json#_define-snippets-in-json-schemas
This is a non-standard schema extension of course. From the source code of Json.NET Schema, it looks like I cannot override the class that is used to serialize the schema to JSON, so I can't figure out how to make this work.
The only approach I have considered is to emit the schema, read it back as dumb JSON and then edit in the snippets. The resulting file could be a .vsschema or something like that and presumably no longer valid in the schema validator, so I would store it next to the "clean" one. Is there any nice way to do this that doesn't require me to path through the resulting JSON and make edits that way?
I'm using Symfony\Component\Serializer\Serializer, and I'm not sure what the difference between the serialize and encode methods is. They have identical signatures, and in practice they seem to give identical output.
Based on the official docs, serializing involves two phases: normalizing and encoding. Normalizing converts input data into array, while encoding crunches that array down to desirable format (be it JSON, XML or something else).
The serialize method of the Symfony Serializer is a wrapper on its encode method. Note that you can call the encode method separately. The serialize method can call the normalize method before the encode method depending on the fact that the requested encoder (eg: json) needs normalization or not.
If you intend to do a JSON serialization, the encode method of the serializer will eventually call json_encode PHP native method. And this method performs a serialization in fact...
For example, if you look into the jsonSerialize method of the jsonSerializable native class of PHP, you can read in the description:
Serializes the object to a value that can be serialized natively by json_encode().
So, at least, in the case of the JSON format, we can say that encoding is serializing in fact but in lower level.
If you call the encode method directly without using the serialize method, you will serialize your data into the expected format but will not take benefits of the normalize process if needed.
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
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.
An example would be that I am consuming json from an api. The api is not consistent in how it returns the json. Say you have an Author and it has a property of Books[]. The api is unfortunately choosing to return Author.Books (of type Book) in cases when there is only one book. The prefered method would be to return just one Book inside Author.Books[].
Json.NET understandably throws a serialization exception when I try to have it deserialize a chunk of json and it finds "Author":{"Book":{... mixed in with "Author":{"Book":["...
Is there a way around this?
Does this answer your question?
Deserializing JSON when sometimes array and sometimes object
I guess the best would be fix the json through a regex replace before sending to the deserializer. If you put here a full sample of a json provided by the API, and a json accepted, i could make the regex for you.