Cannot deserialize an object using a converter? - json.net

Given a JSON string of the form {"$type":"MyType, MyAssembly","seed":0"}, why can't JsonConvert.DeserializeObject utilize the JsonConverter associated with "MyType"?
I've tried decorating the MyType class with a [JsonConverter(typeof(MyType))] attribute. Doesn't work. The custom JsonConverter's ReadJson method is never called.
I've tried adding the custom converter to the serializer's settings Converters collection and made sure the CanConvert method returns true for 'MyType' and the CanRead method returns true. Doesn't work. Neither the converter's CanConvert nor its ReadJson method is ever called.
The DeserializeObject method needs to be able to deserialize a JSON string containing an object whose type is unknown at compile time, but whose type is embedded in the JSON object via the special "$type" member. So don't suggest using DeserializeObject<T> or point out that it works for members, whose type is identified in the contract before hand.
FYI, this problem generalizes to cases where the deserialization needs to identify the object type solely from the embedded "$type" member, so for example, it also fails to resolve a converter if the JSON object is in an untyped JSON array, not just at the top-level.
Basically, an object cannot survive a round trip through the serialization/deserialization process, because although the WriteJson method will be called for the Converter when SerializeObject is called, when you subsequently pass the JSON string to DeserializeObject, it fails to call the converter's ReadJson method, and instead constructs an new instance and uses the basic member population routines.

Related

No parameterless constructor defined for an imported object type to be deserialized from JSON

Dim result = New JavaScriptSerializer().Deserialize(Of SearchResult)(Request.Cookies.Get("user").Value)
An exception of type 'System.MissingMethodException' occurred in System.Web.Extensions.dll but was not handled in user code
Additional information: No parameterless constructor defined for type of 'System.DirectoryServices.SearchResult'.
I see there have been many questions regarding this issue, but the required object types were self-defined class, so the solution would be to create a new and parameterless constructor for that class.
In my case, I am trying to use SearchResult from namespace System.DirectoryServices as the object type to be deserialized from JSON String. How can I solve it?
You can't deserialise a SearchResult object because it has no public constructor.
In theory you could write a JavaScriptConverter and use reflection to instantiate an instance of the target class in the convertor's Deserialize() method but that would be hackery of the first order.
Either serialize and deserialize a custom class of your own making, or rethink what you're doing.

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

How to 'package' request parms into one object

If you have a controller method which has a whole bunch of parameters such as:
getSomething (String a, int b, Timestamp c, etc...)
what is the best way to replace those with an object, so you do not have to then instantiate a new object and set all those from the parameters, like so:
SomeObject o = new SomeObject();
o.setA(a);
o.setB(b);
o.setC(c);
etc..
// use o on other method calls to prepare a response
I have tried #ModelAttribute like so:
getSomething (#modelAttribute SomeObject o)
but it does not seem to work well unless you only use simple types for properties such as strings and ints. A Timestamp property for example causes it to fail with a "Bad Request"
#RequestBody could work, but with some pretty significant changes required to your method call which ends up that you can no longer simply call that method by the browser anymore to test it, which makes development much more annoying.
Is there no way to tell Spring to accept a bunch of parameters in a regular http GET request and use them to instantiate an object for you with the ability to work with all property data types?
You probably need to write a type converter for the Timestamp class, and register it with Spring MVC ConversionService.
See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html
Why can't you use a Date or DateTime (Joda Time) class?
Make sure you use the #Timestamp annotation if using JPA

Workflow: Trying to pass an object variable to a class method

I am having a tough time trying to pass a parameter into my method when I go to invoke it.
I new up a variable called setupNewCase, then I populate it with data. Once I do that, I then try to invoke the method. It normally works when I don't have a value to pass into it, but it doesn't work here in this case as I am trying to pass something into it.
To pass parameters to the invoked method you use the Parameters property on the InvokeMethod activity. Its available on the activity's properties grid and not directly on the designer.
You would use TargetObject when invoking a method on an instance object but since your CommonMethods class is static you won't ever instantiate it and therefore TargetObject should be empty.

JsonConverter is not used on certain types of containers

I have a class that inherits from JsonConverter:
JsonDataBagCreationConverter<T> : JsonConverter where T : IDataBag
I have a class Company that implements IDataBag
When I deserialize a single property of Company JsonDataBagCreationConverter has its ReadJson method invoked as I expect.
When I deserialize an array of Company, JsonDataBagCreationConverter has its ReadJson method invoked as I expect.
It also works for generic lists of Company.
But for certain containers of Company json.net will not recognize that the contents of the list is of type Company. So JsonDataBagCreationConverter is not used when I deserialize.
ie containers of type
System.Collections.DictionaryEntry,
System.Collections.ArrayList,
System.Collections.Hashtable,
System.Collections.SortedList
that stores Company objects.
I know that these containers are non-generic.
Is it possible to make the (de-)serializer look at the contents of these containers and use the JsonDataBagCreationConverter when the contents is Idatabag (ie a company)?
Best regards
Jan
Remove the where T : IDataBag from the converter and override CanConvert and write your logic to check your type there and accordly return true or false.

Resources