I need to implement remote connectivity for an existing reporting interface, which requires serialisation and de-serialisation of the data classes. Here is a simplified version of the classes and interfaces:
public interface IBase
{
string Name { get; }
}
public interface IDerived1
{
int Value { get; }
}
public interface IDerived2
{
bool Value { get; }
}
public class Base : IBase
{
public string Name { get; protected set; }
}
public class Derived1 : Base, IDerived1
{
public int Value { get; protected set; }
}
public class Derived2 : Base, IDerived2
{
public bool Value { get; protected set; }
}
As a input parameter I get
IEnumerable<IBase> reportingData
So this collection may contain any number and combination of instances of 'Derived1' and 'Derived2'. I then serialise the collection like this:
string serialisedReportingData = JsonConvert.SerializeObject( reportingData );
Which gives me for example this:
[{"Value":11,"Name":"Product Number"},{"Value":false,"Name":"Output 1 Enabled"}]
Obviously with this data alone, de-serialisation is impossible, as the type of the individual collection entries is not in the JSON. I could for example make the type part of the JSON or provide an additional collection of types for use during de-serialisation.
I have used CustomCreationConverter overloads before to deal with
JsonConvert.DeserializeObject<IEnumerable<Ixxx>>( ... );
type of scenarios, but this only applied to a single interface type inside the IEnumerable. In my example above I have two: IDerived1 and IDerived2.
My questions / issues:
a) I am not sure how a CustomCreationConverter could be written that deals with more than one interface type and I don't know how to get the type into this.
b) I would love your suggestions on how to implement a solution that would give me the same de-serialisation output as the 'IEnumerable reportingData' I received as input.
I would much appreciate a working code example, where possible.
Many thanks in advance, Christian
The Newtonsoft. JSON namespace provides classes that are used to implement the core services of the framework. It provides methods for converting between . NET types and JSON types.
Newtonsoft. Json package is not provided by RestSharp, is marked as obsolete on NuGet, and no longer supported by its creator.
Use the Newtonsoft. Json; To build and run the app, press F5 or select Debug > Start Debugging. Select the Click Me button to see the contents of the TextBlock object replaced with JSON text.
Today, JSON is one of the main formats for representing complex structures and data exchange. Therefore, all major programming languages have built-in support for working with it. C# is no exception.
Update: (inspired by the comment from dbc)
You should use a SerializationBinder when deserializing with type names. See here for the KnownTypesBinder. (Newtonsoft.Json Version greater 10 is needed)
First, if you want to set your properties you have to make them public
.
Then you can use a JsonSerializerSettings
to Serialize/Deserialize.
List<IBase> loList = new List<IBase>();
loList.Add(new Base() { Name = "Base" });
loList.Add(new Derived1() { Name = "Derived1", Value = 3 });
loList.Add(new Derived2() { Name = "Derived2", Value = true });
KnownTypesBinder loKnownTypesBinder = new KnownTypesBinder()
{
KnownTypes = new List<Type> { typeof(Base), typeof(Derived1), typeof(Derived2) }
};
IEnumerable<IBase> reportingData = loList.AsEnumerable();
JsonSerializerSettings loJsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects,
SerializationBinder = loKnownTypesBinder
};
string lsOut = JsonConvert.SerializeObject(reportingData, loJsonSerializerSettings);
reportingData = JsonConvert.DeserializeObject<IEnumerable<IBase>>(lsOut, loJsonSerializerSettings);
If you use the JsonSerializerSettings
like that, the type information will be include in the json string.
[{
"$type": "Base",
"Name": "Base"
}, {
"$type": "Derived1",
"Value": 3,
"Name": "Derived1"
}, {
"$type": "Derived2",
"Value": true,
"Name": "Derived2"
}
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With