Search code examples
c#genericsjson.netgeneric-listjson-deserialization

How can I deserialize a json file back into the generic list from which it was Serialized?


I am using JSON.NET to serialize a generic list to a json file. It's working fine, but I don't know how to reverse the process - read in the json file and inflate the generic list with its contents.

I have a very simple class:

public class AssignmentTypesLU
{
    public int AssignmentID { get; set; }
    public string AssignmentName { get; set; }
}

...and a generic list to hold instances of it:

List<AssignmentTypesLU> assignmentTypesList;

I then populate the generic list if the file does not already exist (theoretically, the condition is only true once):

if (!System.IO.File.Exists(ASSIGNMENT_TYPES_FILENAME))
{
    List<AssignmentTypesLU> atluList = new List<AssignmentTypesLU>();
    AssignmentTypesLU atlu = new AssignmentTypesLU();
    atlu.AssignmentID = 1;
    atlu.AssignmentName = "Bible Reading";
    atluList.Add(atlu);

    atlu = new AssignmentTypesLU();
    atlu.AssignmentID = 2;
    atlu.AssignmentName = "Initial Call";
    atluList.Add(atlu);

    . . .

    // Serialize contents of list to json file
    var jsonAssignmentTypesLU = JsonConvert.SerializeObject(atluList);
    System.IO.File.WriteAllText(ASSIGNMENT_TYPES_FILENAME, jsonAssignmentTypesLU);
}

But I then want to open the json file and read the contents back into the generic list. The only thing I've got so far is:

// Now open these files and read their contents into the lists declared above.
if (System.IO.File.Exists(ASSIGNMENT_TYPES_FILENAME))
{
    var jsonContents = System.IO.File.ReadLines(ASSIGNMENT_TYPES_FILENAME);
    assignmentTypesList = JsonConvert.DeserializeObject<List<AssignmentTypesLU>>(jsonContents);
}

...but with that (admittedly kind of a wild guess) I get, "cannot convert from 'System.Collections.Generic.IEnumerable' to 'string'"

What is the correct way to accomplish this?


Solution

  • From the Deserialize JSON from a file, you can load the file into a string, then deserialize that:

        var jsonContents = System.IO.File.ReadAllText(ASSIGNMENT_TYPES_FILENAME);
        assignmentTypesList = JsonConvert.DeserializeObject<List<AssignmentTypesLU>>(jsonContents);
    

    Or deserialize directly from a stream:

        using (var reader = System.IO.File.OpenText(ASSIGNMENT_TYPES_FILENAME))
        using (var jsonReader = new JsonTextReader(reader))
        {
            var serializer = JsonSerializer.CreateDefault();
            assignmentTypesList = serializer.Deserialize<List<AssignmentTypesLU>>(jsonReader);
        }
    

    File.ReadLines() returns an IEnumerable<string>. There is no Deserialize overload to deserialize an enumerable of strings.

    For large files, streaming directly will be more performant. From Json.NET: Performance Tips

    To minimize memory usage and the number of objects allocated, Json.NET supports serializing and deserializing directly to a stream. Reading or writing JSON a piece at a time, instead of having the entire JSON string loaded into memory, is especially important when working with JSON documents greater than 85kb in size to avoid the JSON string ending up in the large object heap.