I am trying to serialize and deserialize a polymorphic type hierarchy using a custom JsonConverter
along the lines of the ones shown in answers to How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?. However, when I call the ReadJson()
method of the converter to deserialize some JSON I previously serialized, it crashes. How can I use the converter to deserialize my JSON?
The following code reproduces the problem. It is a simplification of the original code with only one subtype in the polymorphic type hierarchy.
using System;
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace testJSON
{
class Program
{
public List< Ente > ListaEntes = new List< Ente >();
static void Main(string[] args)
{
Program program = new Program();
program.ListaEntes.Add( new Enemy( 10 ) );
program.ListaEntes.Add( new Enemy( 20 ) );
JsonSerializer serializer = new JsonSerializer();
serializer.TypeNameHandling = TypeNameHandling.Objects;
serializer.Formatting = Formatting.Indented;
string folder = "C:\\Users\\pablo\\PasotaPV8_data\\archivoPrueba.dat";
StreamWriter sw = new StreamWriter( @folder );
JsonWriter writer = new JsonTextWriter( sw );
serializer.Serialize( writer, program.ListaEntes );
writer.Close();
sw.Close();
program.ListaEntes.Clear();
StreamReader sr = new StreamReader( @folder );
JsonEnteConverter jsonEnteConverter = new JsonEnteConverter();
JsonReader reader = new JsonTextReader( sr );
program.ListaEntes = ( List< Ente > ) jsonEnteConverter.ReadJson( reader, null, null, serializer );
}
}
public class Ente
{
public string tipo;
public Animator animator;
}
public class Enemy : Ente
{
public Enemy()
{
animator = new Animator( this );
}
public Enemy( int pVar )
{
tipo = "enemigo";
}
}
public class Animator
{
Ente father;
public Animator( Enemy pEnemy )
{
father = pEnemy;
}
}
public class JsonEnteConverter : Newtonsoft.Json.Converters.CustomCreationConverter< Ente >
{
public override Ente Create( Type objectType )
{
throw new NotImplementedException();
}
public Ente Create( JObject jObject )
{
string type = jObject.Property( "tipo" ).ToString(); //get property Type from your json
switch ( type )
{
case "enemigo":
return new Enemy();
}
throw new ApplicationException(String.Format("Type not found", type));
}
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
{
JObject jObject = JObject.Load( reader );
var targetObject = Create( jObject );
serializer.Populate( jObject.CreateReader(), targetObject );
return targetObject;
}
}
}
And the error:
Unhandled exception. Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1. at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings) at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader) at testJSON.JsonEnteConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) in C:\proyectos\proyectosC#\bugJSON\Program.cs:line 90 at testJSON.Program.Main(String[] args) in C:\proyectos\proyectosC#\bugJSON\Program.cs:line 35
Demo fiddle reproducing the problem here: https://dotnetfiddle.net/cbjYMw.