Serializing / deserializing DataTrees with Json.NET

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…

3 Likes