0

I'm trying some different serialization formats for a project. I'm fairly new to serialization, so I had been using the BinaryFormatter because it works out of the box for my solution, but I wanted to do some testing and see how Newtonsoft JSON fared in comparison.

Here is a rough outline of the Dictionary I am trying to (de)serialize.

Dictionary<string, MyObjectList> myDictionary;

where each MyObject in that list of Dictionary values also has a List of different objects

I had been serializing by doing

using(Filestream file = File.Create(path))
    using(Streamwriter sw = new Streamwriter(file))
{
    sw.Write(JsonConvert.SerializeObject(dictionary, Formatting.Indented));
}

And de-serializing by doing

dictionary = JsonConvert.DeserializeObject<Dictionary<string, MyObjectList>>(File.ReadAllText(path));

I get returned the exception:

JsonSerializationException: Cannot create and populate list type MyObjectList

*edit to add List class code as requested

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

//  List of BossLog instances that makes up the Values in BossLogDictionary
[System.Serializable]
public class BossLogList : IEnumerable
{
    public string bossName { get; private set; }

    private List<BossLog> data { get; set; }

    public BossLogList()
    {
        data = new List<BossLog>();
    }
    public BossLogList(string bossName)
    {
        this.bossName = bossName;
        data = new List<BossLog>();
    }

    //  Wrapper for add
    public void Add(in string logName)
    {
        data.Add(new BossLog(bossName, logName));
    }

    //  Wrapper for List.RemoveAll using just a passed string and omitting the int return value
    public void RemoveAll(string logName)
    {
        data.RemoveAll(log => log.logName.CompareTo(logName) == 0);
    }

    //  IEnumerable interface
    public IEnumerator GetEnumerator()
    {
        return ((IEnumerable)data).GetEnumerator();
    }

    //  Wrapper for List.Contains checking with a passed logName parameter
    public bool Exists(string logName)
    {
        return data.Exists(bossLog => bossLog.logName.CompareTo(logName) == 0);
    }

    //  Wrapper for List.FindIndex checking with a passed logName parameter
    public int FindIndex(string logName)
    {
        return data.FindIndex(bossLog => bossLog.logName.CompareTo(logName) == 0);
    }

    //  Wrapper for List.Find checking with a passed logName parameter
    public BossLog Find(string logName)
    {
        return data.Find(bossLog => bossLog.logName.CompareTo(logName) == 0);
    }

    //  Wrapper for List.Count
    public int Count { get { return data.Count; } }

    //  Return a custom struct with our total data
    public LogDataStruct GetBossTotalsData()
    {
        LogDataStruct logDataStruct = new LogDataStruct();
        foreach(BossLog log in data)
        {
            logDataStruct.kills += log.kills;
            logDataStruct.time += log.time;
            logDataStruct.loot += log.loot;
        }

        return logDataStruct;
    }
}

  • 1
    Please, share the `MyObjectList` and your json, currently your question in too broad – Pavel Anikhouski May 31 '20 at 09:24
  • @PavelAnikhouski Added the entire list class to the post. Not sure exactly what you mean by my json? I had already posted the code I was trying to use to serialize and de-serialize the dictionary. I'm using NewtonSoft JSON added to my solution in Visual Studio using NuGet. – Zachary Mitchell May 31 '20 at 13:28
  • You added `BossLogList` to your question. Is that actually `MyObjectList`? Might you please [edit] your question to share a [mcve] that either populates a `MyObjectList` and tries to round-trip it, or tries to deserialize JSON that is included in the question? – dbc May 31 '20 at 14:08
  • However if your `MyObjectList` is just an `IEnumerable` then that's your problem, Json.NET doesn't know how to add items to an untyped enumerable. Instead either 1) Make it an `ICollection` for some `T`, or 2) Make it an `IEnumerable` and add a constructor that takes an existing `IEnumerable`, e.g. `public MyObjectList(IEnumerable items)`. – dbc May 31 '20 at 14:09
  • 1
    @dbc ICollection worked. Thanks for the heads up. Makes sense now that I think about it. – Zachary Mitchell May 31 '20 at 16:08
  • Good, looks like a duplicate of [Deserializing json into a list of objects - Cannot create and populate list type](https://stackoverflow.com/q/36926867/3744182), specifically #2 from [this answer](https://stackoverflow.com/a/36927170/3744182). – dbc May 31 '20 at 16:23

0 Answers0