c#: Serializing an object having interface as properties in readable format - c#

I searched, but couldn't find a satisfying answer. I know there are serializers like: DataContractJsonSerializer, JavaScriptSerializer to do that. But these required a weird requirement of specifying 'KnownType', which is not possible in my scenario as object i am serializing belongs to generic library, and actual implementations of interface could come from client.
Any suggestions ?

ServiceStack has a JSON serializer which doesn't require specifying the known types:
var json = JsonSerializer.SerializeToString(myObj);
Or using extension methods you can call ToJson on any object:
var json = myObj.ToJson();

Json.Net has a method SerializeObject. This would do the job for you.
It's signature is:
public static string SerializeObject(object value);
usage:
using Newtonsoft.Json;
...
string jsonData = JsonConvert.SerializeObject(obj);

Related

Can JSON.NET serialise an object using a "sidecar" approach?

The normal approach to serialisation is to apply attributes to your class to describe how serialisation (or deserialization) is to proceed. For example:
[DataContract]
class MyClass
{
[DataMember]
public string Name { get; set; }
}
Is there a way to perform serialisation using JSON.NET without applying attributes to your class, but instead by providing a "sidecar" object that describes what aspects of the class are to be serialised, in some fashion.
The reason I ask relates to separation of concerns. If you have an API that is meant to be agnostic about how requests get to it, then the natural extension of that is that your API data structures should not be getting embellished with serialisation attributes.
Now of course I could take the "content" of one of my API result objects and copy it into another object having a class that does have appropriate serialisation attributes, but in some cases it would seem more desirable to say "Hey, I want to serialise this object, and the object has no serialisation attributes, so here is a separate data structure to describe what to do."
The other place where this would be handy, of course, is with third-party libraries where you have no opportunity to modify the objects (again, you could make copies of the values, but I'm looking for other ways).
You can use JsonSerializerSettings to specify various serialization options. You can specify whether to serialize or not a particular property, how to serialize a particular type or convert its value, and etc.
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
.....
};
settings.Converters.Add(new StringEnumConverter { CamelCaseText = true });
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.Binder = new SomeSerializationBinder(new DefaultSerializationBinder());
var result = JsonConvert.SerializeObject(yourObject, settings);

JSON Deserialize complex derived object using Newtonsoft JSON.NET [duplicate]

This question already has an answer here:
Best way to store serialization related info between serialization and deserialization
(1 answer)
Closed 9 years ago.
class Packet
{
public Action{get;set;}
}
class Action
{
string Type;
}
class ConcreteAction1 : Action
{
base.Type="ConcreteAction1";
}
class ConcreteAction2 : Action
{
base.Type="ConcreteAction2";
}
I receive Packet class which contains various derived class from Action class, by default every ConcreteActions are deserialized as base class Action, but I want them to be deserialized as their actual types(ConcreteAction1 ,ConcreteAction2...)
Is there a way to achieve this?
Use .Parse() to parse it to an object and then cast, or use .DeserializeObject<T>() to deserialize it to your object. Then see if the return value is correct, if not try something else. Or try to use an identifier to see which of the concrete types it is and hook into the deserializer. But this might not be the most ideal solution.
Alternatively, if you are generating the JSON yourself, you can play with the settings.
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
When you serialize it, it will write the actual concrete type into the JSON and when you deserialize it will transform it into the concrete type.
JsonConvert.Deserialize(input, null, settings)
But, perhaps someone has a better idea. :)

when we serialize serializable object using JSON.Net, JSON string is different from DatacontractJSON serializer

I have a class some thing like below
[Serializable]
public class sample
{
private int m_width;
private int m_height;
public int Width
{
get
{
return this.m_width;
}
set
{
this.m_width = value;
}
}
public int Height
{
get
{
return this.m_height;
}
set
{
this.m_height = value;
}
}
}
If I use DataContractJsonSerializer to serialize the object of this class i get the json string as below:
{"m_height":1345,"m_width":1234}
If I use Newtonsoft.Json.dll to serialize this I am getting the out put like below:
{"Width":1234,"Height":1345}
Why DataContractSerializer using backing fields for serialization if class marked as serializable ?
Is there any way I can achieve the same thing using Newtonsoft.Json.dll
We have some objects which are marked as [Serializable] so they can be serialised using traditional methods, but which we need to have cleanly serialised in JSON for use with Web API. Setting IgnoreSerializableAttribute to true will stop Newtonsoft.Json from behaving like Microsoft's serialisers and instead it will just serialise the public properties.
TLDR: Add this to WebApiConfig.cs:
((Newtonsoft.Json.Serialization.DefaultContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver).IgnoreSerializableAttribute = true;
Unless you are always communicating from WCF to WCF, your best bet is probably going to be to use the Newtonsoft serializer. Unfortunately, the MS serializer seems to follow some Microsoft-specific standards that do not match the standards that many web apps expect.
Newtonsoft's serializer seems to be more standard, and even MS uses it for WebAPI, and in the Web API http client (nuget will pull it down for you).
Here's another difference that you will find -- try serializing a DateTime type. You will find that the DataContract serialzer serializes the value in a different format that is not compatible with other JSON (you will notice some slashes in it). My understanding is that that alternate format was used by some of the AJAX WebForm controls, but it's specific to Microsoft Webforms.
Here's a little more info about the dates: http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx
Here's another thing you might look at:
The differences between DataContractJsonSerializer and Newtonsoft still stand, but as for why you are getting the weird serialization behavior -- you are mixing your serialization standards.
The [Serializable] attribute pertains to the older .Net serialization. DataContractSerialization is backward compatible, but the behavior might be different.
If you want to do this the datacontract way, mark you class with the
[DataContract] attribute instead, and mark each public member that you want to serialize with the [DataMember] attribute. (or remove all serialization attributes, and it should default to all public properties)
That should explain the difference that are seeing, but I would still recommend that you prefer the Newtonsoft serializer.
DefaultContractResolver class in Newtonsoft.Json.dll i found some code which is setting IgnoreSerializableAttribute property to true.
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE || PORTABLE40)
IgnoreSerializableAttribute = true;
#endif
I am using the DotNet4.0 dll so this property set to true and it is ignoring the Serializable attribute. if i make it false it is giving the same output as DataContractSerializer
DataContract serializer requires you to explicitly mark the class with the [DataContract] attribute and then mark each desired property to be serialized with the [DataMember] attribute.
If you do that you will find that the same json string will get out as using the other class.
The issue you are encountering is due to differences of how the 2 serializers treat the default serialization (without additional information specified):
DataContract serializes all private fields unless otherwise specified
NewtonSoft serializes all public properties unless otherwise specified
On how you can make Newtonsoft serialize the private fields i have no other idea than making a wrapper class with m_Width and m_Height properties that on the setters and geters put the values in the correct target properties of the actual object

JSON writer - drop in replacment for xmlwriter?

Without having spent a lot of time on this subject, I'm curious what might be the most straightforward way to allow my existing code to serialize to json in addition to xml. The existing code uses a xmlwriter to perform some sophisticated serialization for a specific purpose, so ultimately I'd like to be able to pass a jsonserializer in place of the xml one and have it produce json instead of xml.
Do any of the json libs handle something like this?
No, there's no direct drop-in replacement. The APIs for existing JSON serializers is much different. They need to have the entire model in memory and serialize it in one step. For example with JSON.NET you would use:
string json = JsonConvert.SerializeObject(product);
The correct way to achieve what you are looking for is to abstract the actual serialization of the object behind an interface:
public interface IMySerializer
{
void Serialize(MyObject instance, Stream stream);
}
Now you could have multiple implementations of this interface such as MySerializerXml, MySerializerJson, MySerializerCsv, ...
Now the code that depends on the serialization would simply work with an IMySerializer. So when you need to handle a new format all you have to do is drop-in an implementation of this interface.
There is no direct replacement for an XmlWriter. If you want to support both XML and JSON, I would suggest serialising via data-contracts, i.e. use attributes on your data objects to indicate the desired serialised format. Take a look at DataContractJsonSerializer for JSON and DataCOntractSerializer for XML.
Your model objects would look something like this:
[DataContract(Name = "Customer", Namespace = "http://www.contoso.com")]
class Person
{
[DataMember()]
public string FirstName;
[DataMember]
public string LastName;
[DataMember()]
public int ID;
}

Using XmlSerializer with private and public const properties

What's the simplest way to get XmlSerializer to also serialize private and "public const" properties of a class or struct? Right not all it will output for me is things that are only public. Making it private or adding const is causing the values to not be serialized.
XmlSerializer only looks at public fields and properties. If you need more control, you can implement IXmlSerializable and serialize whatever you would like. Of course, serializing a constant doesn't make much sense since you can't deserialize to a constant.
Even though it's not possible to serialize private properties, you can serialize properties with an internal setter, like this one :
public string Foo { get; internal set; }
To do that, you need to pre-generate the serialization assembly with sgen.exe, and declare this assembly as friend :
[assembly:InternalsVisibleTo("MyAssembly.XmlSerializers")]
Check out DataContractSerializer, introduced in .NET 3.0. It also uses XML format, and in many ways, it is better than XmlSerializer, including dealing with private data.
See http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/ for a full comparison.
If you only have .NET 2.0, there's the BinarySerializer that can deal with private data, but of course it's a binary format.
It doesn't make sense to consider const members, as they aren't per-instance; but if you just mean non-public instance members: consider DataContractSerializer (.NET 3.0) - this is similar to XmlSerializer, but can serialize non-public properties (although it is "opt in").
See here for more.
One other solution the use of Newtonsoft.Json:
var json = Newtonsoft.Json.JsonConvert.SerializeObject(new { root = result });
var xml = (XmlDocument)Newtonsoft.Json.JsonConvert.DeserializeXmlNode(json);
Sure, this one has unfortunately detour via json.
Here's my solution to putting immutable values in a property that will serialize to XML:
[XmlElement]
public string format { get { return "Acme Order Detail XML v3.4.5"; } set { } }

Categories