You don't need to implement it by yourself. JSON.NET has native support for it.
You have to specify the desired TypeNameHandling option for the JSON formatter, like this (in global.asax
application start event):
JsonSerializerSettings serializerSettings = GlobalConfiguration.Configuration
.Formatters.JsonFormatter.SerializerSettings;
serializerSettings.TypeNameHandling = TypeNameHandling.Auto;
If you specify Auto
, like in the above sample, the parameter will be deserialized to the type specified in the $type
property of the object. If the $type
property is missing, it will be deserialized to the parameter's type. So you only have to specify the type when you're passing a parameter of a derived type. (This is the most flexible option).
For example, if you pass this parameter to a Web API action:
var param = {
$type: 'MyNamespace.MyType, MyAssemblyName', // .NET fully qualified name
... // object properties
};
The parameter will be deserialized to an object of MyNamespace.MyType
class.
This also works fro sub-properties, i.e., you can have an object like this, which specifies that an inner property is of a given type
var param = {
myTypedProperty: {
$type: `...`
...
};
Here you can see a sample on JSON.NET documentation of TypeNameHandling.Auto.
This works at least since JSON.NET 4 release.
NOTE
You don't need to decorate anything with attirbutes, or do any other customization. It will work without any changes in your Web API code.
IMPORTANT NOTE
The $type must be the first property of the JSON serialized object. If not, it will be ignored.
COMPARISON TO CUSTOM JsonConverter/JsonConverterAttribute
I'm comparing the native solution to this answer.
To implement the JsonConverter
/JsonConverterAttribute
:
- you need to implement a custom
JsonConverter
, and a custom JsonConverterAttribute
- you need to use attributes to mark the parameters
- you need to know beforehand the possible types expected for the parameter
- you need to implement, or change the implementation of your
JsonConverter
whenever your types or properties change
- there is a code smell of magic strings, to indicate the expected property names
- you are not implementing something generic that can be used with any type
- you're reinventing the wheel
In the author of the answer there's a comment regarding security. Unless you do something wrong (like accepting a too generic type for your parameter, like Object
) there is no risk of getting an instance of the wrong type: JSON.NET native solution only instantiates an object of the parameter's type, or a type derived from it (if not, you get null
).
And these are the advantages of JSON.NET native solution:
- you don't need to implement anything (you only have to configure the
TypeNameHandling
once in your app)
- you don't need to use attributes in your action parameters
- you don't need to know the possible parameter types beforehand: you simply need to know the base type, and specify it in the parameter (it could be an abstract type, to make polymorphism more obvious)
- the solution works for most cases (1) without changing anything
- this solution is widely tested, and optimized
- you don't need magic strings
- the implementation is generic, and will accept any derived type
(1): if you want to receive parameter values that don't inherit from the same base type, this will not work, but I see no point on doing so
So I can't find any disadvantages, and find many advantages on JSON.NET solution.
WHY USING CUSTOM JsonConverter/JsonConverterAttribute
This is a good working solution that allows customization, that can be modified or extended to adapt it to your particular case.
If you want to do something that the native solution cannot do, like customizing the type names, or inferring the type of the parameter based on available property names, then do use this solution adapted to your own case. The other one cannot be customized, and will not work for your needs.