Deserialising an implementation of an interface - c#

Similar to JSON.NET deserialize to object with Type parameter, I need to deserialise some JSON, which has been previously serialised:
Serialisation code:
...
Data = new ImplementationofICommandData{ Id = Id }
DataType = typeof(ImplementationofICommandData).AssemblyQualifiedName,
...
Deserialisation code:
...
(ICommandData)JsonConvert.DeserializeObject(dto.Data, Type.GetType(dto.DataType))
...
In this case, dto.DataType contains the AssemblyFullName.
Initially, the projects that contained the serialisation and deserialisation shared a project with DTOs in it, so the deserialisation was able to use the same AssemblyQualifiedName for the type.
Now, I have a new project that is serialising data to the database. I have a DTO in the original shared project that has the exact same structure as the DTO in the new project, but due to being in a different assembly, the AssemblyQualified name that gets serialised does not correspond to a type about which the deserialising code knows.
Ideally, I won't have to make the serialisation and deserialisation code share the same DTO project, so is it possible to get the type by something less than the AssemblyQualifiedName? Or is there a better approach?

As it stands, I've added a default namespace/assembly to search for a bare class name. This could be expanded to allow for a non-hack method of registration of a list of namespaces/assemblies in which to search for the DTO class, all wrapped up in some kind of resolver class.

Related

Dynamically deserialize from JSON

I have some JSON here. The problem is it doesn't match the classes data types anymore. My question is; is it possible to deserialize JSON Dynamically? i.e. if I have entirely different JSON's can I deserialize them into two entirely different classes without first knowing what class I want to deserialize each into.
You can deserialize dynamic object with using newtonsoft
like bellowing code piece.
dynamic dynamicObj = JsonConvert.DeserializeObject(jsonStr);
string name = dynamicObj.data.code;
But in my personal preference is using strong type. I think its more convenience.
you can use quictype for generating c# classes from JSON object
quicktype generates strongly-typed models and serializers from JSON,
JSON Schema, and GraphQL queries, making it a breeze to work with JSON
type-safely in any programming language.
Hope the answer helps to you.

Dummy Objects Good or Bad

I am working on a project that communicates a lot of data with a server. This data is in a json format. We end up creating a lot of dummy objects to parse the json data. This leads to having a lot of classes that just contain class members. Is there a better way of doing things?
thanks
Assuming that you are using NewtonSoft's JSON parser or something similar, you have a couple of choices here. The usual use case here is to deserialize to a named type, thus:
var parsedMessage = JsonConvert.DeserializeObject<Message>(content.AsString());
If you have many types for each differnet JSON message type you wish to receive and wish to avoid to, you can do the following:
var parsedMessage = JsonConvert.DeserializeObject<dynamic>(content.AsString());
This will give you a dynamic object that you can inspect and should also work given other Json libraries. Alternatively, NetwtonSoft also provides the following method:
public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject);
This will allow you to deserialize to an anonymously typed object rather than a dynamic object.

How to deserialize JSON into a List<KeyValuePair<string,string>> set

I have some JSON data :-
{
"mail":"mitch#domain.com",
"givenName":"User",
"sn":"Name",
"uid":"mitch",
"gecos":"User Name"
}
What I'm trying to do is de-serialize this into a List<KeyValuePair<string,string>>
I would normally do a dictionary, however some key's may be duplicated - this is the representation that is automatically generated by .NET when I pass a List<KeyValuePair<string,string>> object into the System.Web.Script.Serialization.JavaScriptSerializer class.
When I just plug the serialized object into the System.Web.Script.Serialization.JavaScriptDeserializer I get a empty response back.
From what I can see it should not be possible using the JavaScriptSerializer. The only way for customizing its behavior is by means of a JavaScriptConverter class, that will allow you to customize the serialization/deserialization process. Unfortunately both methods will pass an IDictionary for the properties, therefore the duplicated names are already merged. You might want to look into either a different format for your JSON or a different serialization library such as JSON.net which is way more customizable.

Automatically map asmx-provided xml data to POCO object

In my .net code I am consuming a third-party asmx service that provides me data in Xml format. So basically, I am recieving a structure in a form of XmlNode:
<PostcodeEntry>
<Postcode>13542</Postcode>
<Postcodename>Odessa</Postcodename>
</PostcodeEntry>
Currently, to map it to my POCO object I have to manually iterate through a corresponding ChildNode's and retrieve their InnerText value to get the actual data:
var PostCodeNode = entryNode.SelectSingleNode("Postcode");
if (PostCodeNode != null)
{
result.PostCode = PostCodeNode.InnerText;
}
In case I need to map a large info structure, the code grows to a messy code-scroll.
Is there a way I can improve this so I don't have to write the parsing manually? What is the best practice for this?
I believe that you have different options depending on how you get your data and how you like to design your code etc. From your brief description I can think of at least these two:
Create an XML Serializer - for example by marking up your class with Xml Attributes and de-serialize the XML directly as your desired object via the serializer. The disadvantage of this approach is that you will create a strong coupling between your serializer and your business object. Please take a look at something like this: http://www.switchonthecode.com/tutorials/csharp-tutorial-xml-serialization.
Create a proxy object and map your proxy object to your business object. You can create the proxy object either by using a WSDL exposed by the asmx service, or by using the XSD.exe tool or similar (you may need to first generate an XSD based on the XML if the XML is not already described by an XSD). Then you can map the properties of your proxy object to the properties of your business object. This will provide you a more clean separation between the objects, but at the same time it requires more work.
Br. Morten
You can create SoapClient object for WebService, then you can return the Response as List<>. You need to change the Ouput response to List<>.
example Consilder this the webservice to consume, http://xxx.xx.xxx.xxx/CosmosService/Cm_Service.asmx
then add Service Reference in your application, Click On Advanced Button, change the Collection Type System.Collections.GenericList.
then you can Consume WebService Methods as List<> directly like this
CosmosRef.CM_ServiceSoapClient client = new CosmosRef.CM_ServiceSoapClient();
List<CosmosRef.Product> listProduct = client.GetAllProducts("Computers", 1);
dataGrid1.DataContext = listProduct;

Posting a collection of subclasses

I have a requirement for users to edit a list of quotes for a lead, the quotes can be different types such as:
QuoteForProductTypeA
QuoteForProductTypeB
All quote types share a common base class, such as QuoteBase.
I have my quotes displaying fine on the front end, and appear to post back the correct data too.
However, on the server it doesn't obviously doesn't know which subclass to use, so just uses the base class.
I think i need some kind of custom model binder for WebApi to check for a hidden field such as ModelType which contains the type of the object in the collection, the model binder then creates a new object of this type and binds the properties from my posted values to this object.
However, i am stuck at this point with very little documentation / blogs on how to do this.
I have checked the source code for WebApi to see if i can extend a default model binder, but any defaults are sealed classes.
I can only implement IModelBinder by the looks of it, i can create the correct model type by looking for a value called ModelType, but then i'm not sure how to fill the rest of the values in my subclasses, if there was a default model binder i was inheriting from i would just call the base classes bind method.
If your post collection comes from request body, it won't go through model binder. Web API will use formatter to deserialize the content.
If you just want to support json, it's quite easy. Just add following code to your web api config:
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
The setting will let json.net to save type name in the payload if the runtime type is different with the declare type. When you post it back, json.net will deserialize the payload to the type you specified in the payload.
A sample payload looks like:
{"$type":"MvcApplication2.Models.Car, MvcApplication2","SeatCount":10,"WheelCount":4,"Model":0,"Brand":null}]

Categories