Skip to content

System.Text.Json IgnoreReadOnlyProperties not working for enumerables #80113

Open

Description

@npp127

Description

Given a class

    public class Test
    {
        public int MyProperty1 { get; set; } = 69;

        public int MyProperty2 { get; } = 420;

        public IEnumerable<int> Collection1 { get; set; } = new int[] { 69, 420 };

        public IEnumerable<int> Collection2 { get; } = new int[] { 69, 420 };
    };

by setting IgnoreReadOnlyProperties to true, one would expect that only "MyProperty1" and "Collection1" would be serialized.
Collection2 Gets also serialized for whatever reason.

Reproduction Steps

Test class

namespace T
{
    public class Test
    {
        public int MyProperty1 { get; set; } = 69;
        public int MyProperty2 { get; } = 420;

        public IEnumerable<int> Collection1 { get; set; } = new int[] { 69, 420 };

        public IEnumerable<int> Collection2 { get; } = new int[] { 69, 420 };
    };
}

Program.cs

using System.Text.Json;
using T;

var opt = new JsonSerializerOptions()
{
    IgnoreReadOnlyProperties = true,
    WriteIndented = true,
};


var obj = new Test();

var json =  JsonSerializer.Serialize(obj, opt);

Console.WriteLine(json);

Csproj

<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net7.0</TargetFramework>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
		<LangVersion>latest</LangVersion>
	</PropertyGroup>
</Project>

Expected behavior

{
  "MyProperty1": 69,
  "Collection1": [
    69,
    420
  ]
}

Actual behavior

{
  "MyProperty1": 69,
  "Collection1": [
    69,
    420
  ],
  "Collection2": [
    69,
    420
  ]
}

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Jan 3, 2023
  2. npp127 commented on Jan 3, 2023

    @npp127
    Author

    it's like that by design for enumerables and dictionaries

    if ((EffectiveConverter.ConverterStrategy & (ConverterStrategy.Enumerable | ConverterStrategy.Dictionary)) != 0)
    {
    // Properties of collections types that only have setters are not supported.
    if (Get == null && Set != null && !_isUserSpecifiedSetter)
    {
    CanDeserialize = false;
    }
    }
    else
    {
    // For read-only properties of non-collection types, apply IgnoreReadOnlyProperties/Fields policy,
    // unless a `ShouldSerialize` predicate has been explicitly applied by the user (null or non-null).
    if (Get != null && Set == null && IgnoreReadOnlyMember && !_isUserSpecifiedShouldSerialize)
    {
    CanSerialize = false;
    }
    }

    Properties of collections types that only have setters are not supported.

    But should they?

    I'm missing whats the point of the reasoning for not supporting that.
    Something like .IgnoreReadOnlyEnumerables with false as a default would allow users to avoid this behaviour

  3. reopened this on Jan 3, 2023
  4. ghost removed
    untriagedNew issue has not been triaged by the area owner
    on Jan 3, 2023
  5. added this to the 8.0.0 milestone on Jan 17, 2023
  6. ghost removed
    untriagedNew issue has not been triaged by the area owner
    on Jan 17, 2023
  7. added
    untriagedNew issue has not been triaged by the area owner
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Jan 17, 2023
  8. krwq commented on Jan 17, 2023

    @krwq
    Member

    I'm marking this as 8.0 for now because we should define behavior for this in #78556 and they should be looked at hollistically

  9. eiriktsarpalis commented on Jan 17, 2023

    @eiriktsarpalis
    Member

    Duplicate of #67514 and #37599. IIUC this is intentional behavior and collections are treated specially w.r.t. this flag. Changing this now would be a breaking change. We might consider solving this using a different flag that supersedes IgnoreReadOnlyProperties.

  10. added
    enhancementProduct code improvement that does NOT require public API changes/additions
    and removed on Jan 17, 2023
  11. npp127 commented on Jan 17, 2023

    @npp127
    Author

    Duplicate of #67514 and #37599. IIUC this is intentional behavior and collections are treated specially w.r.t. this flag. Changing this now would be a breaking change. We might consider solving this using a different flag that supersedes IgnoreReadOnlyProperties.

    Shouldn't this behaviour be made configurable from the options?

  12. modified the milestones: 8.0.0, Future on Jun 16, 2023
  13. eiriktsarpalis commented on Jun 16, 2023

    @eiriktsarpalis
    Member

    Moving to Future.

  14. wiz0u commented on Dec 16, 2023

    @wiz0u

    Same for getter-only arrays. They get serialized, even though they are obviously not deserializable (can't set or resize the array)

    My test program:

    using System.Text.Json;
     
    var test = new Test();
    Console.WriteLine(JsonSerializer.Serialize(test, new JsonSerializerOptions { IgnoreReadOnlyProperties = true }));
    
    public partial class Test
    {
    	public int Id => 123;
    	public int[] SomeArrayProp => new[] { 456 };
    	public IEnumerable<int> SomeIEnumProp { get { yield return 789; } }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-System.Text.JsonenhancementProduct code improvement that does NOT require public API changes/additions

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions