Search code examples
c#jsonserializationlistobject

C# JSON deserialize a file into object list fails with convert String to Collection error


I've got a little project for school and we are dealing with some json stuff here. I can write down a object List into JSON and this file is a valid JSON format. No once I load the very same file I do receive an error complaining about not beeing able to convert. Here is the message:

Newtonsoft.Json.JsonSerializationException
  HResult=0x80131500
  Message=Error converting value "[
  {
    "ID": 500455154,
    "Title": "GameOne",
    "MinAge": 14,
    "Price": 12.8,
    "State": "New",
    "Players": 4
  },
  {
    "ID": 860100321,
    "Title": "Gametwo",
    "MinAge": 14,
    "Price": 12.8,
    "State": "New",
    "Players": 4
  },
  {
    "ID": 358239485,
    "Title": "Gamethree",
    "MinAge": 14,
    "Price": 12.8,
    "State": "New",
    "Players": 4
  }
]" to type 'System.Collections.Generic.List`1[Ludothek.Game]'. Path '', line 1, position 513.
  Source=Newtonsoft.Json
  StackTrace:
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
   at Ludothek.DATA.loadData_Games() in epos\Ludothek\Ludothek\DATA.cs:line 71
   at Ludothek.Program.Main(String[] args) in \r\Program.cs:line 16

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List`1[Ludothek.Game].

This is my function to load this file and push it into an existing List of game:

public List<Game> loadData_Games()
        {
            var Gl = new List<Game>();
            string[] files = Directory.GetFiles(folder, "games.json");
            foreach (var file in files)

                using (StreamReader sr = new StreamReader(file))
                {
                    using (JsonReader jsr = new JsonTextReader(sr)) {
                        var Serializer = new JsonSerializer();

                        Gl = (List<Game>)Serializer.Deserialize(jsr, typeof(List<Game>));
// above is where it hits the fan...
                    }


                }

        
            return Gl;
        }

And of course here is the game class:

public class Game : AbstGame
    {

        [JsonProperty("ID")]
        public override int ID { get ; }
        [JsonProperty("Title")]
        public override string Title { get ; set ; }
        [JsonProperty("MinAge")]
        public override int MinAge { get ; set ; }
        [JsonProperty("Price")]
        public override double Price { get; set ; }
        [JsonProperty("State")]
        public override string State { get; set ; }
        [JsonProperty("Players")]
        public int Players { get; set; }
        
        public Game(string title, int minAge, double price,string state, int players)
        {
            Random rnd = new Random();
            ID = rnd.Next(1, 999999999);
            Title = title;
            MinAge = minAge;
            Price = price;
            State = state;
            Players = players;

        }

and this is how I write it down:

        public void backUp_Games(List<Game> games)
        {
            string filename = "games";
               string jsonGames = JsonConvert.SerializeObject(games,Formatting.Indented);
            backUp(filename, jsonGames);


        }
        public void backUp(string fileName ,string json)
        {
            string filename = @"C:\.....\Desktop\JsonTest\"+fileName+".json"; // not the actual path ;)
            File.WriteAllText(filename, JsonConvert.SerializeObject(json,Formatting.Indented));

        }

I really travelled the internet to find a solution to this problem and tried already several other approaches. I cant spot the issue. Does anyone else see it and could give me a hint?

What I do in code is like generate a List of games with some attributes. Once the window gets closed, I will push that games object list into json and safe it, once we open it it reloads. So it has to get the object list out of json.

Many thanks in advance!


Solution

  • and this file is a valid JSON format

    Yes, it's valid JSON but not what you expect. You write a file with only one JSON string.

    Simplified example:

    "foo"
    

    This is valid json. It's just a string. You do the same but the string content looks like JSON.

    "{\"foo\": \"bar\"}"
    

    This is still just one string no JSON object.

    That's why you get the error: Could not cast or convert from System.String to System.Collections.Generic.List`1[Ludothek.Game].

    Here's what you do...

    string jsonGames = JsonConvert.SerializeObject(games,Formatting.Indented);
    // string jsonGames is the JSON you want but then you do...
    File.WriteAllText(filename, JsonConvert.SerializeObject(json,Formatting.Indented));
    

    So, you do the JSON encoding two times and JSON encoding a JSON string will result in a string as described above.

    Solution: Encode only once.