System.Text.Json silent null on List<> when respecting CS8618 #97639
-
DescriptionWhen respecting CS8618 aka not using a setter with a List<> property, we noticed that deserializing a model with System.Text.Json silently keeps the property to null, despite existing values in the JSON response. While I agree that there should be a setter to the property, I also expected a NullReferenceException. Reproduction StepsRepro code namespace JsonTest;
using System.Text.Json;
internal class Program
{
static void Main()
{
var json = "{\"Id\": 3, \"Types\":[{\"Name\": \"Model1\"}, {\"Name\": \"Model2\"}]}";
var deserialized = JsonSerializer.Deserialize<Model>(json);
}
}
public class Model
{
public int Id { get; set; }
// Respecting CS8618 by not using a setter
public List<ModelType> Types { get; }
}
public class ModelType
{
public string Name { get; set; }
} Expected behaviorI the json example from the snippet, I would expected the deserialization to fail with NullReferenceException or something similar as the expected outcome is to add items to a list, but the list is null. Actual behaviorThe list is returned null. Regression?No response Known WorkaroundsNo response Configuration.Net 8, Win11, x64 Other informationNo response |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I'm not sure I understand this, the presence of a setter shouldn't have an impact on whether CS8618 is emitted. In this case, the warning occurs because the value isn't being initialized by the default constructor, despite there not being a setter defined.
This is by design, the serializer will not consider for deserialization any properties that are missing a setter (because they are inherently not writable). One exception to this rule is public class Model
{
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
public List<ModelType> Types { get; } = []; // Initialize to avoid CS8618
} However my own preference is to just use an init-only property (since you avoid the attribute): public class Model
{
public List<ModelType> Types { get; init; } = [];
} You can even avoid the initialization by marking the property as required: public class Model
{
public required List<ModelType> Types { get; init; }
} Hope this helps. |
Beta Was this translation helpful? Give feedback.
I'm not sure I understand this, the presence of a setter shouldn't have an impact on whether CS8618 is emitted. In this case, the warning occurs because the value isn't being initialized by the default constructor, despite there not being a setter defined.
This is by design, the serializer will not consider for deserialization any properties that are missing a setter (because they are inherently not writable). One exception to this rule is
JsonObjectCreationHandling.Populate
w…