I am using Newtonsoft.Json to serialize/deserialize my C# object to/from JSON.
My C# object has a property of following type:
List<BaseClass> objects { get; set; }
This collection holds different child objects (e.g. - ChildClass1, ChildClass2).
Serializing to JSON works fine but while deserializing it creates objects of BaseClass in collection (which is obvious :)).
Is there a way I can create concrete child objects while deserializing?
I tried creating a custom converter by implementing CustomCreationConverter<BaseClass>. But the problem is overridden Create method gives me just the type and based on that I cannot decide which object to return (ChildClass1 or ChildClass2)
My JSON string has a Type property by which I can identify the child object to create.
Any help is highly appreciated.
You can use the TypeNameHandling option:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }
JsonConvert.SerializeObject(myObject, Formatting.Indented, settings );
The TypeNameHandling option "Auto" ensures that type names are included in the serialized JSON
for subclasses. But watch out: these names become invalid when the classes or their namespaces are renamed!
Related
Throughout my project I have a singleton service class that takes care of (de)serializing, with something like this:
_setting = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects,
Converters = new List<JsonConverter>() { new MyConverter() },
TraceWriter = new Iov.Common.Json.TraceWriter(),
Formatting = Formatting.Indented,
SerializationBinder = binder,
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
};
The service will be used in a multi-threaded environment, i.e. several (de)serializing tasks will - at the same time - use the above JsonSerializerSettings with my custom JsonConverter.
Up to now the converter has been stateless, but for deserializing I'm considering tracking the state, i.e. current position within the JSON object, child/parent-relationships. The converter would need to store/cache its results (basically in the ReadJson override) in some kind of stack/list.
All (de)serialize calls are wrapped in the mentioned service's methods, so I could easily implement using a new instance of the JsonSerializerSettings with my custom JsonConverter for each call.
Assuming my initial assumption is correct that the JsonConverter is thread-agnostic and therefore multithreading-safe as long as its stateless, my question is: can I rely on the JsonConverter to always deserialize objects in the same order?
I know that the order in which members are populated is not defined (as the order in a Dictionary is not), but will it always deserialize "from leaf to branch"?
We are serialising an object to JSON which has a property that is an array of dynamic objects, e.g.:
public List<dynamic> Widgets { get; set; }
public string Name {get;set;}
The serialisation is set to use the built in camel case resolver, with the option ProcessDictionaryKeys set to true, as per advice from this post :
var contractResolver = new CamelCasePropertyNamesContractResolver();
contractResolver.NamingStrategy.ProcessDictionaryKeys = true;
jsonSerializerSettings.ContractResolver = contractResolver;
However the resultant JSON retains the pascal case (which is how the objects are stored in the database) for the entries in this field. All other properties get converted to camel case as expected.
Example output for the above:
{
name:"test",
widgets:[{Name:"Widget1",Description:"A nice widget"}]
}
So why does the naming strategy only apply to strongly typed C# objects and not these dynamic values?
I have verified the obvious things, i.e. ensured the serialisation settings are being applied.
Thanks to dbc for the help.
In case anyone else has the issue, the problem was that the underlying object was a JObject - for some reason I assumed it would be an ExpandoObject.
JSON.net will not respect the naming conventions for JObjects, they are serialised as-is so you must come up with some solution to manually convert the object keys.
I chose a custom object converter, as per this post: How to serialize a JObject the same way as an object with Json.NET?
JSON.Net works well if I give a custom generic type to Deserialize method. But, when I change the output object type as JToken, it does not finish the deserialization process through given serializer setting.
I must notify the deserializer that put this property into that model property (e.g. => the property will be deserialized: "date_add" will be: "DateAdd" in the model). I do not want to use attributes.
When I debug my code below, CustomContractResolver does not work even I put the breakpoint into there.
Here is my code:
var model = JsonConvert.DeserializeObject<JToken>(content,
new JsonSerializerSettings() {ContractResolver = new CustomContractResolver()});
I used the $type properties in Json for the deserialization of inherited objects (to choose the correct object type in which to deserialize at runtime)
I do this using :
config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings{ TypeNameHandling = TypeNameHandling.Objects}
this line is in the WebApiConfig file.
It works fine but I can't figure out how to restrict the $type only to the webservices who actually needs it (I only need it for one PUT and one POST).
The $type is messing up the API results for the other webservices and I can't find some TypeNameHandling configuration nor some serialization option to avoid this.
Does anyone knows how to do that?
Cheers!
To enable type name handling on a nested object, you can attach [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Objects)] to the containing property, like so:
public class RootObject
{
[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Objects)]
public object Data { get; set; }
}
There's no builtin way to enable type name handling on a specific type, and so there's no builtin way to enable type name handling on the root object. Instead, you could use the EnableJsonTypeNameHandlingConverter from SignalR Typenamehandling if you need to do this.
Thanks for the help dbc. I had other issues during deserialization (using a OData.Delta object and the solution you proposed didn't actually fit completely the need.
I overcame the issue thanks to this post : Custom Json.NET serializer settings per type
to have the $type customization only for a few webservices.
I ma using Newtonsofts' Json.Net to serialize some and array of objects to json.
The objects have a common set of properties but also have Meta property which is a dictionary
During serialization I want the key value pairs to be added to my json object as if they where root level properties, like this...
{
id: 1,
name:'jeff',
food:'spinch',
spoon: 'ýes'
}
Not like this:
{
id: 1,
name:'jeff',
meta:{
food:'spinch',
spoon: 'ýes'
}
}
I have dug through JsonSerializerSettings but cant seem to spot where I can jump in and override???
You can do this by creating your own JsonConverter and then adding an attribute to the class you want to serialize
[JsonConverter(typeof(MyConverter))]
Example here -
http://www.lostechies.com/blogs/rhouston/archive/2008/02/25/a-custom-converter-for-json-net.aspx
If your dictionary is a string to object dictionary could can simply use the [JsonExtensionData] attribute:
[JsonExtensionData]
public Dictionary<string, object> Meta { get; set; }
See How to serialize a Dictionary as part of its parent object using Json.Net.
You could use the .Net DataContractJsonSerializer.
For custom serialization, see:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.idatacontractsurrogate.aspx
One advantage of using IDataContractSurrogate (compared to simply adding properties to your class for serialization) is that you don't have to mix actual properties and serialization properties together in the same class.
Another advantage (compared to having to do custom serialization against a property bag, ala KeyValuePairConverter) is that you only have to add attributes to properties on your classes (the actual type and the surrogate type) and you can write all your conversion/custom serialization code directly against those types. This keeps your code higher level, and lets the framework deal with the exact transport mechanism.