0

I have a problem with deserialized Dictionary. I can't cast objects from Dictionary to my type Remiza... I'm using Json.net and what I can see is that objects in Dictionary are JObject not Object and I can't cast them to my type. Here is my serialization/deserialization code:

    private static Dictionary<Type, List<Object>> _ekstensje = new Dictionary<Type, List<Object>>();

    public static void SerializeDictionary()
        {
            string json = JsonConvert.SerializeObject(_ekstensje);
            System.IO.StreamWriter file = new System.IO.StreamWriter(@"c:\tmp\dictionary.json");
            file.WriteLine(json);

            file.Close();
        }

        public static void DeserializeDictionary()
        {
            string json;
            System.IO.StreamReader file = new System.IO.StreamReader(@"c:\tmp\dictionary.json");
            json = file.ReadToEnd();

            file.Close();
            _ekstensje = JsonConvert.DeserializeObject<Dictionary<Type, List<Object>>>(json);//Deserializacja Dictionary
            Debug.WriteLine(_ekstensje);
        }

        public static List<Object> GetEkstensja(Type className)
        {
            List<Object> list = _ekstensje[className];
            return list;
        }

Exectution:

        ObjectPlus.DeserializeDictionary();
        List<Object> list = ObjectPlus.GetEkstensja(typeof(Remiza));
        foreach (Object o in list)
        {
            Remiza r = (Remiza) o;
            listaRemiz.Add(r);
        }

My problem is when casting to "Remiza" I have that exception:

An exception of type 'System.InvalidCastException' occurred in Osek_MAS_WPF.exe but was not handled in user code. Additional information: Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Osek_MAS_WPF.Remiza'.

Thanks for any help!

2
  • If you use a dictionary of object type, the best JSON.net can offer you is Jobject. you're not specifying the type it should try to parse into, so you're not going to be able to get a more specific class out of it. You can write a custom deserializer or put a strong type there. Or leave it as Jobject and parse the entries manually. Commented Feb 7, 2016 at 16:54
  • Ok, so how can I parse those entries manually from JObject to my type? Thats exactly what I'm trying to achieve. Commented Feb 7, 2016 at 16:56

2 Answers 2

1

This should allow you to convert the JObect to your Remiza type.

ObjectPlus.DeserializeDictionary();
    List<Object> list = ObjectPlus.GetEkstensja(typeof(Remiza));
    foreach (Object o in list)
    {
        Remiza r = o.ToObject<Remiza>();
        listaRemiz.Add(r);
    }

I got this from the stackoverflow answer at the link below. If what I put doesn't work take a look at the link and it should help you to get it running.

https://stackoverflow.com/a/10221594/634769

Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately in my Class Remiza I have list of Persons where Person is abstract class and it's not working because it can't create instance of Person... An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code Additional information: Could not create an instance of type Osek_MAS_WPF.Osoba. Type is an interface or abstract class and cannot be instantiated. I'm starting to think that serialization isn't the best solution to keep class extension... When there are that kind of associations it's not working as we can see..
He have to actually cast the object to JObject before using ToObject. Remiza r = ((JObject)o).ToObject<Remiza>();
0

In order to successfully serialize and deserialize polymorphic types with Json.NET, you need to set TypeNameHandling = TypeNameHandling.Auto, like so:

public class ObjectPlus
{
    // Replace with whatever file name is appropriate.  My computer doesn't have a "c:\tmp" directory.
    static string JsonFileName { get { return Path.Combine(Path.GetTempPath(), "dictionary.json"); } }

    static JsonSerializerSettings JsonSettings { get { return new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Formatting = Formatting.Indented }; } }

    private static Dictionary<Type, List<Object>> _ekstensje = new Dictionary<Type, List<Object>>();

    public static void SerializeDictionary()
    {
        var path = JsonFileName;

        using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
        using (var writer = new StreamWriter(stream))
        {
            var serializer = JsonSerializer.CreateDefault(JsonSettings);
            serializer.Serialize(writer, _ekstensje);
        }
    }

    public static void DeserializeDictionary()
    {
        var path = JsonFileName;
        try
        {
            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = new StreamReader(stream))
            using (var jsonReader = new JsonTextReader(reader))
            {
                var serializer = JsonSerializer.CreateDefault(JsonSettings);
                _ekstensje = serializer.Deserialize<Dictionary<Type, List<Object>>>(jsonReader);
            }
        }
        catch (FileNotFoundException)
        {
            // File was not created yet, dictionary should be empty.
            _ekstensje.Clear();
        }
    }

    public static List<Object> GetEkstensja(Type className)
    {
        List<Object> list = _ekstensje[className];
        return list;
    }

    public static void AddEkstensja<T>(T obj)
    {
        List<Object> list;
        if (!_ekstensje.TryGetValue(obj.GetType(), out list))
            list = _ekstensje[obj.GetType()] = new List<object>();
        list.Add(obj);
    }

    internal static string ShowJsonContents()
    {
        if (!File.Exists(JsonFileName))
            return string.Empty;
        return File.ReadAllText(JsonFileName);
    }
}

You should now be able to serialize and deserialize your dictionary when it contains an instance of Remiza.

This will work for types that serialize to objects or collections. However, if your dictionary contains types that serialize to JSON primitives -- for instance an enum or a long -- you may need to encapsulate them in a type wrapper along the lines of Deserialize specific enum into system.enum in Json.Net.

(Incidentally, your _ekstensje dictionary isn't thread-safe.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.