Search code examples
c#jsonserialization

How to prevent serialization of read only collection properties using System.Text.Json.JsonSerializer?


Create a class with a read-only collection property. Serialize using System.Text.Json.JsonSerializer with options to specify IgnoreReadOnlyProperties = true. Read only collection properties are still being serialized, whereas other read only properties are not serialized. Upon deserializing all read only properties are ignored as expected.

Why are collections treated differently upon serialization?

Can I prevent serialization of a read only collection property without [JsonIgnore] attributes?

The choice of serialization method is out of my hands so I am hoping to have no serialization specific attributes in my code.

With the following test class:

public class TestJSONClass
{
   public int ReadOnlyInt { get; } = 1;
   public IEnumerable<int> ReadOnlyCollection { get; } = new int[2];

   public int ReadWriteInt { get; set; } = 3;
   public IEnumerable<int> ReadWriteCollection { get; set; } = new int[4];
}

Then serialized by:


JsonSerializerOptions options = new JsonSerializerOptions() { WriteIndented = true, IgnoreReadOnlyProperties = true };
JsonSerializer.Serialize(new TestJSONClass(), options);

I get the output below. As expected ReadOnlyInt is not serialized. However, ReadOnlyCollection is serialized.

{
  "ReadOnlyCollection": [
    0,
    0
  ],
  "ReadWriteInt": 3,
  "ReadWriteCollection": [
    0,
    0,
    0,
    0
  ]
}

I aim to get the following:

{
  "ReadWriteInt": 3,
  "ReadWriteCollection": [
    0,
    0,
    0,
    0
  ]
}

Solution

  • IgnoreReadOnlyProperties/Fields = true does not apply to Collections.

    Source: https://github.com/dotnet/runtime/issues/37599#issuecomment-669742740

    The reason is to ensure that rule CA2227 can be applied and still use JsonSerializer to deserialize a collection https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2227?view=vs-2019

    My best guess is using [JsonIgnore]. If you cannot or don't want to use it, you could write your own converter/rules. But I think that isn't easy at all.