skip to Main Content

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
  ]
}

2

Answers


  1. 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.

    Login or Signup to reply.
  2. one of the ways how to avoid serialization of a property is to mark the property as internal, then it won’t be serialized.

    So in your case, change your line

    public IEnumerable<int> ReadOnlyCollection { get; } = new int[2];
    

    to

    internal IEnumerable<int> ReadOnlyCollection { get; } = new int[2];
    

    You will get the following result:

    {
      "ReadWriteInt": 3,
      "ReadWriteCollection": [
        0,
        0,
        0,
        0
      ]
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search