Skip to content

[API Proposal]: Extend JsonIgnoreCondition #66490

Closed

Description

@WeihanLi

Background and motivation

Sometimes we may want to ignore some properties only when serialize, included when deserialize, currently, we had JsonIgnoreCondition

public enum JsonIgnoreCondition
{
  Never,
  Always,
  WhenWritingDefault,
  WhenWritingNull,
}

Maybe we could add new conditions like WhenWriting/WhenReading(or WhenSerializing/WhenDeserializing ...)

API Proposal

edited

namespace System.Text.Json.Serialization;

public enum JsonIgnoreCondition
{
  Never = 0,
  Always = 1,
  WhenWritingDefault = 2,
  WhenWritingNull = 3,
+ WhenWriting = 4,
+ WhenReading = 5,
}

API Usage

public class TestModel
{  
  [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)]
  public int Age { get; set; }
  [JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)]
  public string Name { get; set; }
}

var json = JsonSerializer.Serialize(new TestModel{ Age = 10, Name="Mike" });
Assert.Equal("{\"Age\":10}", json);

json = "{\"Age\":10, \"Name\":\"Mike\"}";
var model = JsonSerializer.Deserialize<TestModel>(json);
Assert.Equal("Mike", model.Name);
Assert.Equal(0, model.Age);

Alternative Designs

No response

Risks

No response

Activity

  1. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on Mar 11, 2022
  2. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Mar 11, 2022
  3. changed the title [-][API Proposal]: Extension `JsonIgnore`[/-] [+][API Proposal]: Extend `JsonIgnoreCondition`[/+] on Mar 11, 2022
  4. eiriktsarpalis commented on Mar 11, 2022

    @eiriktsarpalis
    Member

    Related to #55781. In general we want to be careful about adding more states in the JsonIgnoreCondition enum, and we generally want to encourage a contract model customization approach via #63686. However your proposals seem fairly straightforward and simple to implement, so I'd support their addition.

  5. added this to the Future milestone on Mar 11, 2022
  6. eiriktsarpalis commented on Mar 11, 2022

    @eiriktsarpalis
    Member

    Tagging @layomia for a second opinion. If this seems reasonable, I think I can mark it ready for review.

  7. Symbai commented on Mar 12, 2022

    @Symbai
  8. ScarletKuro commented on Jun 1, 2022

    @ScarletKuro

    There should be WhenReadingNull too, I'm actually surprised that it's absent. Because the obsolete IgnoreNullValus was working on reading too.
    For example:

    public class TestClass
    {
          public string FirstName { get; set; } = string.Empty;
          public string[] List { get; set; } = Array.Empty<string>();
          public TestClass(){}
    }

    And deserialization

    var testClassJson = "{\"FirstName\":null,\"List\":null}";
    TestClass testclass1 = JsonSerializer.Deserialize<TestClass>(testClassJson, new JsonSerializerOptions()
    {
          IgnoreNullValues = true
    });

    This will produce:

    FirstName: ""
    List: string[0]
    

    Meanwhile you can't express such behavior with DefaultIgnoreCondition or the [JsonIgnore(Condition = ...)] yet the Microsoft Documentation says you not to use IgnoreNullValues when all the behavior of this property wasn't ported.
    NB! small note that if you won't explicitly set the FirstName:null in json the the FirstName will have empty string after deserialization, but this is not enough.
    I'd say this is a major problem when you want to counteract null values when some 3rd party sends you null but you don't want it to have, you want an empty array, empty string, etc etc instead.

    FYI: the Newtonsoft.Json is able to ignore null values on reading with [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]

    Also, the issue #62086 shows that I'm not alone thinking the same way that there should be attribute for null deserialization and how misleading the documentation / obsolete attribute on IgnoreNullValues is.

  9. Stabzs commented on Jun 16, 2022

    @Stabzs

    This is a tremendous problem and I JUST ran into this during an upgrade.

    The fact that this wasn't thought through as a potential migration path and called out in the documentation is incredibly frustrating, especially since as @ScarletKuro pointed out, this behavior previously worked in IgnoreNullValues and an upgrade has no immediately obvious backwards-compatible option.

    It would be so greatly appreciated if there was a little more foresight around deprecating functionality coupled with an appreciation for how that functionality is being used, and a little less opinion on what you think is the appropriate usage, without regards to how it worked previously.

  10. ScarletKuro commented on Jun 16, 2022

    @ScarletKuro

    @layomia said to just suppress the warring and use IgnoreNullValues because they do not plan to remove it. But my problem with that is that IgnoreNullValues is an global parameter within JsonSerializerOptions and it works in both direction - serialization and deserialization. In my case, I want it to be only for deserialization. Also, I want to have control over what property can ignore null and what must not ignore on deserialization. Like having an attribute is nowhere close as having just IgnoreNullValues.
    I know that the aim is not to copy paste Newtonsoft.Json features, but this one is a simple and useful feature(for some even a stop factor). I was surprised when team said they didn't find much reason to add it in JsonIgnoreCondition, but as I said earlier the ability to counteract nulls, for example, that you don't want the list to be null but empty array is pretty big already, imo.

    Update: Also, what I found out, is that IgnoreNullValues is not supported for source generator(i.e. JsonSourceGenerationOptions) meanwhile there is support for the JsonIgnoreCondition that's another reason why there should be WhenReadingNull and etc options.

  11. krwq commented on Jun 28, 2022

    @krwq
    Member

    @ScarletKuro with contract customization you can simply remove Get/Set from property to prevent serialization or deserialization

  12. eiriktsarpalis commented on Jun 28, 2022

    @eiriktsarpalis
    Member

    @krwq would it be possible to write a small snippet here illustrating how this can be done?

  13. 22 remaining items

  14. WeihanLi commented on Aug 4, 2023

    @WeihanLi
    ContributorAuthor

    @ScarletKuro add a new proposal here #90011

  15. eiriktsarpalis commented on Aug 4, 2023

    @eiriktsarpalis
    Member

    Let's use #83706 to track WhenReadingNull.

  16. modified the milestones: Future, 9.0.0 on Sep 20, 2023
  17. onurkanbakirci commented on Sep 20, 2023

    @onurkanbakirci

    @eiriktsarpalis I've already implemented in #69574

  18. removed their assignment
    on Oct 4, 2023
  19. WeihanLi commented on Jul 3, 2024

    @WeihanLi
    ContributorAuthor

    Hello @onurkanbakirci are you still working on this? I'd like to try to take this if you're not going to implement this

  20. eiriktsarpalis commented on Jul 5, 2024

    @eiriktsarpalis
    Member

    @WeihanLi feel free to open a PR.

  21. added
    in-prThere is an active PR which will close this issue when it is merged
    on Jul 8, 2024
  22. modified the milestones: 9.0.0, 10.0.0 on Jul 23, 2024
  23. eiriktsarpalis commented on Jul 23, 2024

    @eiriktsarpalis
    Member

    Moving to 10.0.0 since feature development for .NET 9 is now completed.

  24. locked and limited conversation to collaborators on Dec 2, 2024
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

    api-approvedAPI was approved in API review, it can be implementedarea-System.Text.Jsonhelp wanted[up-for-grabs] Good issue for external contributorsin-prThere is an active PR which will close this issue when it is merged

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions