After a few hours of work I found I could create a custom converter by extending JsonConverter. I used this answer to help me out.
I got my output to look like:
"components": [
{
"name": "position",
"x": 50,
"y": 20
},
{
"name": "health",
"HP": 100
}
]
I added my converter as an attribute to the dictionary like so:
[JsonProperty(Required = Required.Always), JsonConverter(typeof(DictionaryComponentConverter))]
private Dictionary<String, Component> components = new Dictionary<String, Component>();
I then did the same to the Component class though I created a new converter ComponentConverter:
[JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(ComponentConverter))]
class Component
{
protected String name;
public String Name { get { return name; } }
}
It's not how I want the code too look like in the end, Im going to try to clean it but heres how my converters look like:
DictionaryComponentConverter:
class DictionaryComponentConverter : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
// Load JArray from stream
JArray jArray = JArray.Load(reader);
// Create target object based on JObject
List<Component> target = new List<Component>();
// Populate the object properties
serializer.Populate(jArray.CreateReader(), target);
Dictionary<String, Component> dictionary = new Dictionary<string, Component>();
foreach (Component comp in target)
if (!dictionary.ContainsKey(comp.Name))
dictionary.Add(comp.Name, comp);
return dictionary;
}
return new Dictionary<string, Component>();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is Dictionary<String, Component>)
{
Dictionary<String, Component> components = (Dictionary<String, Component>)value;
writer.WriteStartArray();
foreach (KeyValuePair<String, Component> entry in components)
{
serializer.Serialize(writer, entry.Value);
}
writer.WriteEndArray();
}
else
{
writer.WriteStartObject();
writer.WriteEndObject();
}
}
public override bool CanConvert(Type objectType)
{
return typeof(Dictionary<string, Component>).IsAssignableFrom(objectType);
}
}
ComponentConverter:
class ComponentConverter : JsonConverter
{
protected Component Create(Type objectType, JObject jObject)
{
if (jObject["name"] != null)
if (jObject["name"].ToString() == "position")
{
return new Position();
}
else if (jObject["name"].ToString() == "health")
{
return new Health();
}
return new Component();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Load JObject from stream
JObject jObject = JObject.Load(reader);
// Create target object based on JObject
Component target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is Position)
{
Position position = (Position)value;
writer.WriteStartObject();
writer.WritePropertyName("name");
writer.WriteValue(position.Name);
writer.WritePropertyName("x");
writer.WriteValue(position.x);
writer.WritePropertyName("y");
writer.WriteValue(position.y);
writer.WriteEndObject();
}
else if (value is Health)
{
Health health = (Health)value;
writer.WriteStartObject();
writer.WritePropertyName("name");
writer.WriteValue(health.Name);
writer.WritePropertyName("HP");
writer.WriteValue(health.HP);
writer.WriteEndObject();
}
}
public override bool CanConvert(Type objectType)
{
return typeof(Component).IsAssignableFrom(objectType);
}
}