I need to deserialize this json:
[null]
to a List<JsonNode>
unfortunately instead, I get this exception:
System.Text.Json.JsonException: 'The JSON value could not be converted to System.Text.Json.Nodes.JsonNode. Path: $[0] | LineNumber: 0 | BytePositionInLine: 5.'
How to deserialize to a list with a single null value in it?
This code
var toJson = JsonSerializer.Serialize<List<JsonNode>>(new List<JsonNode>{ null });
Gives this json:
[null]
But this code
var fromJson = JsonSerializer.Deserialize<List<JsonNode>>("[null]");
Throws above
Update this is a bug in System.Text.Json which has been fixed in .NET 8 as of Preview 5. See:
List<JsonNode>
or JsonNode []
from a JSON array containing a null entry, e.g. [null]. #92902/A failing .NET 7 demo fiddle was created here.
As a workaround in earlier versions, you could create a custom converter for List<JsonNode>
like the following:
public class JsonNodeListConverter : JsonConverter<IEnumerable<JsonNode?>>
{
public override bool CanConvert(Type objectType) =>
objectType == typeof(List<JsonNode>) || objectType == typeof(IReadOnlyList<JsonNode>) || objectType == typeof(IReadOnlyCollection<JsonNode>) || objectType == typeof(JsonNode []) || objectType == typeof(IEnumerable<JsonNode>);
public override void Write(Utf8JsonWriter writer, IEnumerable<JsonNode?> value, JsonSerializerOptions options)
{
writer.WriteStartArray();
foreach (var node in value)
JsonSerializer.Serialize(writer, node, options);
writer.WriteEndArray();
}
public override IEnumerable<JsonNode?> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartArray)
throw new JsonException();
var list = new List<JsonNode?>();
while (reader.ReadAndAssert().TokenType != JsonTokenType.EndArray)
{
list.Add(JsonSerializer.Deserialize<JsonNode>(ref reader, options));
}
return typeToConvert.IsArray ? list.ToArray() : list;
}
}
public static class JsonExtensions
{
public static ref Utf8JsonReader ReadAndAssert(ref this Utf8JsonReader reader) { if (!reader.Read()) { throw new JsonException(); } return ref reader; }
}
Then use as follows:
var options = new JsonSerializerOptions
{
Converters = { new JsonNodeListConverter() },
};
JsonSerializer.Deserialize<List<JsonNode>>("""[null]""", options)
And you will be able to deserialize lists and arrays of JsonNode
that include null values.
Demo fiddle #2 here.
Alternatively, you could deserialize to an intermediate IEnumerable<object>
with the option JsonSerializerOptions.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode
and your non-null JSON array values will be deserialized as JsonNode
subtypes:
var options = new JsonSerializerOptions
{
UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode,
};
var list = JsonSerializer.Deserialize<IEnumerable<object>>("""[null, [null], 1, {}, "a"]""",
options)
?.Cast<JsonNode?>().ToList();
Demo fiddle #3 here.