I am attempting to migrate serialized JSON objects using an abstract implementation of 开发者_开发百科JsonConverter using Json.NET. The idea is that you would implement this class for any type that you would want to migrate versions. When that type is being deserialized, it calls one or more methods that modify the underlying JSON before using it to create the object.
public abstract class JsonMigrator<T> : JsonConverter<T> where T : class
{
public override void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer)
{
writer.WriteValue(value);
}
public override T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var item = JObject.Load(reader);
//if this is a reference to an earlier object, return already created object
if (item["$ref"] != null)
{
return serializer.ReferenceResolver.ResolveReference(serializer, (string)item["$ref"]) as T;
}
//call migration methods to transform json data
var migratedData = PerformMigrations(item, serializer);
var dataReader = migratedData.CreateReader();
//this doesn't work, infinte recursion
//var created = serializer.Deserialize(dataReader);
//call constructor and then populate with data
var created = ConstructObjectSomehow();
serializer.Populate(dataReader, created);
return created as T;
}
// Inspects object for Version property and performs each migration in succession to bring to current
internal JToken PerformMigrations(JObject serializedData, JsonSerializer serializer)
{
var serializedVersion = serializedData.Value<int>("Version");
for (int i = serializedVersion; i < OrderedMigrations.Count; i++)
{
serializedData = OrderedMigrations[i](serializedData, serializer);
}
return serializedData;
}
public abstract List<Func<JObject, JsonSerializer, JObject>> OrderedMigrations { get; }
}
When I do it this way, it causes a SO because the converter just gets called recursively when I try to create the instance using the serializer.deserialize method. The constructor for the test class I'm using doesn't have a true parameterless constructor, so I can't restrict the generic type to new()
.
I am thinking that I can probably get it to work using reflection and/or Activator.CreateInstance. But I'm wondering if there is a more robust approach, since Json.Net is obviously already able to create instances of this object. (ie. it all works without this converter)
精彩评论