I'm having a peculiar problem with supporting IEnumerable along with JSON serialization. I dug around for a while here and online in general, and I see this issue isn't new. However, what I found was quite old and no longer works when I apply them to my app. I'm on .NET 7.0 and this is a simple Console application. Also, I'm doing this on a Mac (which is kinda cool).
Here's the code that I have (note that the IEnumerable implementation is commented out in class JsonNumberRanges. Also, please forgive me, I haven't coded in C# for about 13 years, so I'm just getting back into it and my knowledge is quite old):
using System.Collections;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace JsonSerializationProblem
{
public class NumberRange
{
int lowerBound;
int upperBound;
public NumberRange()
{
lowerBound = 0;
upperBound = 0;
}
public int LowerBound
{
get => lowerBound;
set => lowerBound = value;
}
public int UpperBound
{
get => upperBound;
set => upperBound = value;
}
}
public class JsonNumberRanges /*: IEnumerable<NumberRange>*/
{
string fileHeader;
List<NumberRange> numberRanges;
public JsonNumberRanges()
{
fileHeader = "This is a sample Json file.";
}
public string FileHeader
{
get => fileHeader;
set => fileHeader = value;
}
public List<NumberRange> NumberRanges
{
get => numberRanges;
set => numberRanges = value;
}
public NumberRange this[int index]
{
get => numberRanges[index];
set => Add(value);
}
internal void Add(NumberRange numberRange)
{
if (numberRanges == null)
{
numberRanges = new List<NumberRange>();
}
numberRanges.Add(numberRange);
}
internal int Count
{
get
{
if (numberRanges == null)
{
return 0;
}
return numberRanges.Count;
}
}
/*
public IEnumerator<NumberRange> GetEnumerator()
{
for (int i = 0; i < numberRanges.Count; i++)
{
yield return numberRanges[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
// Call the generic version of GetEnumerator().
return GetEnumerator();
}
*/
}
}
Here's the main program:
using System;
using System.Text.Json;
namespace JsonSerializationProblem
{
public class Program
{
static void Main()
{
JsonNumberRanges ranges = new JsonNumberRanges();
NumberRange range = new NumberRange();
range.LowerBound = 1;
range.UpperBound = 20;
ranges.Add(range);
range = new NumberRange();
range.LowerBound = 21;
range.UpperBound = 40;
ranges.Add(range);
range = new NumberRange();
range.LowerBound = 41;
range.UpperBound = 60;
ranges.Add(range);
range = new NumberRange();
range.LowerBound = 61;
range.UpperBound = 80;
ranges.Add(range);
range = new NumberRange();
range.LowerBound = 81;
range.UpperBound = 100;
ranges.Add(range);
string fileName = "TestJsonFile.json";
var options = new JsonSerializerOptions { WriteIndented = true };
string jsonString = JsonSerializer.Serialize(ranges, options);
Console.WriteLine(jsonString);
// Write the data to the file.
File.WriteAllText(fileName, jsonString);
// Now, read back from file.
jsonString = File.ReadAllText(fileName);
JsonNumberRanges newRanges = JsonSerializer.Deserialize<JsonNumberRanges>(jsonString);
}
}
}
With the IEnumerable code commented out, the following file is both created and read back in with no problem:
{
"FileHeader": "This is a sample Json file.",
"NumberRanges": [
{
"LowerBound": 1,
"UpperBound": 20
},
{
"LowerBound": 21,
"UpperBound": 40
},
{
"LowerBound": 41,
"UpperBound": 60
},
{
"LowerBound": 61,
"UpperBound": 80
},
{
"LowerBound": 81,
"UpperBound": 100
}
]
}
However, if I uncomment the code that supports IEnumerable, this is the file that is created (notice the FileHeader portion is missing):
[
{
"LowerBound": 1,
"UpperBound": 20
},
{
"LowerBound": 21,
"UpperBound": 40
},
{
"LowerBound": 41,
"UpperBound": 60
},
{
"LowerBound": 61,
"UpperBound": 80
},
{
"LowerBound": 81,
"UpperBound": 100
}
]
So when my code attempts to read the file back in, it crashes with the following call stack:
Unhandled exception. System.NotSupportedException: The collection type 'JsonSerializationProblem.JsonNumberRanges' is abstract, an interface, or is read only, and could not be instantiated and populated. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
---> System.NotSupportedException: The collection type 'JsonSerializationProblem.JsonNumberRanges' is abstract, an interface, or is read only, and could not be instantiated and populated.
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(ReadStack& state, Utf8JsonReader& reader, NotSupportedException ex)
at System.Text.Json.Serialization.Converters.IEnumerableOfTConverter`2.CreateCollection(Utf8JsonReader& reader, ReadStack& state, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
at JsonSerializationProblem.Program.Main() in <PATH REMOVED>/JsonSerializationProblem/Program.cs:line 56
[createdump] Gathering state for process 33717
[createdump] Crashing thread 8af20 signal 6 (0006)
[createdump] Writing crash report to file /var/folders/2r/cm4pgxks7xvd840fcbv30rqh0000gn/T/coredump.33717.crashreport.json
[createdump] Crash report successfully written
[createdump] Writing minidump with heap to file /var/folders/2r/cm4pgxks7xvd840fcbv30rqh0000gn/T/coredump.33717
[createdump] Written 493744296 bytes (120543 pages) to core file
[createdump] Target process is alive
[createdump] Dump successfully written in 2832ms
bash: line 1: 33717 Abort trap: 6 "/usr/local/share/dotnet/dotnet" "<PATH REMOVED>/JsonSerializationProblem/bin/Debug/net7.0/JsonSerializationProblem.dll"
Like I mentioned above, I read a number of threads on Stack Overflow and online and attempted a number of recommended solutions. For example, I tried applying the [JsonObject] which didn't work (one thread suggested this). I looked at the JsonObjectAttribute class because a couple of thread pointed to that. I also found a thread on Reddit where someone was ranting about Microsoft's implementation of JSON support, which wasn't helpful. So far, nothing I've tried has worked.
Has anyone encountered this and were you able to solve it? If so, how did you do it?