I am working on migrating old legacy code from BinaryFormatter usage to Json serialization. One of the challenges is handling serialization for untyped collections, arrays, List, Dictionary etc...
I tried setting TypeNameHandling = TypeNameHandling.All, but for elements/items that are boxed ; structs or enums, Json.Net converts them to string, and Int64 and essentially lose their type. I am wondering if anyone has written a converter or an extension to work with this case. I am not sure if this is a bug or an intended behavior.
Instead of
List<Object> { Point, Enum} == > { "111,222",2}
maybe something like this
{
[{
"$type": "System.Drawing.Point",
"x": 111
"y": 222
}, {
"$type": "System.Windows.WindowState",
"value": 2
}
]
}
Example
I took this example and modified it to a similar case using IList. https://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm
I kept the class names even though they don't make sense for ease of comparison with the original code. I can copy the code and run the code below in LinqPad.
void Main()
{
var stockholder = new Stockholder
{
FullName = "Steve Stockholder",
Businesses = new List<object>
{
new Hotel
{
Name = "Hudson Hotel",
Stars = 4
},
new System.Drawing.Point(1000,1),
WindowState.Maximized
}
};
string jsonTypeNameAll = Newtonsoft.Json.JsonConvert.SerializeObject(stockholder, Newtonsoft.Json.Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(jsonTypeNameAll);
string jsonTypeNameAuto = Newtonsoft.Json.JsonConvert.SerializeObject(stockholder, Newtonsoft.Json.Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
Console.WriteLine(jsonTypeNameAuto);
Stockholder newStockholder = JsonConvert.DeserializeObject<Stockholder>(jsonTypeNameAuto, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
Console.WriteLine(newStockholder.Businesses[0].GetType().Name);
Console.WriteLine(newStockholder.Businesses[1].GetType().Name);
Console.WriteLine(newStockholder.Businesses[2].GetType().Name);
}
public abstract class Business
{
public string Name { get; set; }
}
public class Hotel : Business
{
public int Stars { get; set; }
}
public class Stockholder
{
public string FullName { get; set; }
public IList<object> Businesses { get; set; }
}
Output
{
"$type": "UserQuery+Stockholder, query_avpnnz",
"FullName": "Steve Stockholder",
"Businesses": {
"$type": "System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib",
"$values": [
{
"$type": "UserQuery+Hotel, query_avpnnz",
"Stars": 4,
"Name": "Hudson Hotel"
},
"1000, 1",
2
]
}
}
{
"FullName": "Steve Stockholder",
"Businesses": [
{
"$type": "UserQuery+Hotel, query_avpnnz",
"Stars": 4,
"Name": "Hudson Hotel"
},
"1000, 1",
2
]
}
Hotel
String
Int64
Expected
{
"$type": "UserQuery+Stockholder, query_avpnnz",
"FullName": "Steve Stockholder",
"Businesses": {
"$type": "System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib",
"$values": [{
"$type": "UserQuery+Hotel, query_avpnnz",
"Stars": 4,
"Name": "Hudson Hotel"
}, {
"$type": "System.Drawing.Point",
"x": 1000
"y": 1
}, {
"$type": "System.Windows.WindowState",
"value": 2
}
]
}
}