I'm trying to implement custom serialization using Newtonsoft.Json where I want all fields serialized, and then deserialized to their proper types. The class contains a field of type "object", implements ISerializable
, has a [Serializable]
attribute set, and has a serialization constructor. I set the value of this object field to an instance of some class, then serialize it. I use a JsonSerializer
with TypeNameHandling
set to TypeNameHandling.Auto
.
Here's the code that I'm trying out:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.IO;
using System.Runtime.Serialization;
namespace ConsoleApp1
{
class Program
{
[Serializable]
class Foobar : ISerializable
{
public Foobar()
{
}
public Foobar(SerializationInfo info, StreamingContext context)
{
something = info.GetValue("something", typeof(object));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("something", something);
}
public object Something { get { return something; } set { something = value; } }
private object something;
[JsonIgnore]
private string someOtherObject = "foobar";
}
class SomeOtherClass
{
public string Foo { get; set; }
public string Bar { get; set; }
}
static void Main(string[] args)
{
Foobar myObj = new Foobar();
myObj.Something = new SomeOtherClass() { Bar = "My first", Foo = "fqwkifjwq" };
var serializer = new Newtonsoft.Json.JsonSerializer();
serializer.TypeNameHandling = TypeNameHandling.Auto;
serializer.Formatting = Formatting.Indented;
string serialized;
using (var tw = new StringWriter())
{
using (var jw = new JsonTextWriter(tw))
serializer.Serialize(jw, myObj);
tw.Flush();
serialized = tw.ToString();
}
Foobar deserialized;
using (var rt = new StringReader(serialized))
using (var jsonReader = new JsonTextReader(rt))
deserialized = serializer.Deserialize<Foobar>(jsonReader);
Console.WriteLine("Type of deserialized.Something: " + deserialized.Something.GetType().FullName);
}
}
}
After deserialization, the field Foobar.Something
is simply a Newtonsoft.Json.Linq.JObject
, which is NOT what I want. I would like this to be properly deserialized to an object of type SomeOtherClass
. The serialized output does contain the required info:
{
"something": {
"$type": "ConsoleApp1.Program+SomeOtherClass, ConsoleApp1",
"Foo": "fqwkifjwq",
"Bar": "My first"
}
}
Here's what I've tried so far:
- Using the code above. Does exactly how I describe above.
- Using the
[JsonObject(MemberSerialization = MemberSerialization.Fields)]
attribute on the object I'm serializing. Then I get an object of the correct type on theFoobar.Something
field (aSomeOtherClass
instance), BUT, any non-serialized fields with a default value gets initialized to null instead of their default value (like the fieldFoobar.someOtherObject
). - Removing the
Serializable
attribute. Then theISerializable GetObjectData
and the serialization constructor is not called. - Setting the JsonSerializer's
TypeNameHandling
property toAll
(no effect).
So - any tips on how this can be solved?