According to this there’s the possibility to code a custom json deserializer for specific data types.
I’ve come up with the following. This is the test code (only works if testTree
is a class property, otherwise it doesn’t accept the [JsonConverter...]
attribute):
// Create this as a class property
[JsonConverter(typeof(DataTreeConverter<int>))]
DataTree<int> testTree = new DataTree<int>();
// Call this in some class method
testTree.Add(0, new GH_Path(0, 1));
testTree.Add(13, new GH_Path(0, 1));
testTree.Add(42, new GH_Path(1, 2));
string testTreeJson = JsonConvert.SerializeObject(testTree);
DataTree<int> testTreeDeserialized = JsonConvert.DeserializeObject<DataTree<int>>(testTreeJson);
An this is the custom deserializer
public class DataTreeConverter<T> : Newtonsoft.Json.JsonConverter
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return false; }
}
public override bool CanConvert(Type objectType)
{
return typeof(DataTree<T>).IsAssignableFrom(objectType); //return false;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return string.Empty;
}
else if (reader.TokenType == JsonToken.String)
{
return serializer.Deserialize(reader, objectType);
}
else
{
// This is where the tree is built.
JObject obj = JObject.Load(reader);
// Check if the current JObject has the "BranchCount" parameter.
if (obj["BranchCount"] != null)
{
DataTree<T> tree = new DataTree<T>();
// Get path info and data.
var pathsJson = obj["Paths"];
var dataJson = obj["Branches"];
// Add data to tree.
for (int i = 0; i < pathsJson.Count(); i++)
{
int[] pathIndices = pathsJson[i]["Indices"].ToObject<int[]>();
T[] pathData = dataJson[i].ToObject<T[]>();
tree.AddRange(pathData, new GH_Path(pathIndices));
}
return tree;
}
else
return serializer.Deserialize(reader, objectType);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException("Not implemented yet");
}
}
I know this is a bit cryptic alltogether and I must admit that I understand only 75% of it. I simply post it anyways in case someone else might find it useful…