Search code examples
c#jsonrestjsonserializer

Required Annotation in Sub-Class overrules JsonIgnore Attribute in Main-Class


tldr: serialisation works as expected, deserialisation ignores [JsonIgnore] attribute when ignored child has a [Required] attribute.

I use the System.Text.Json Serializer (Newtonsoft is not included in the Project) to Read/Write a list of parent objects over REST. The parent class has a list of child objects. The Child objects have a referece set back to the parent. Although I talk about childs and parents, they do not inherent from each other. To avoid a loop i set the reference to the parent to [JsonIgnore]. Works on the GET-Endpoint. Failes on the PUT. Error message:

  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-d41897820e0a0771cf9278cb64fb8bb4-36a021adba8a4493-00",
  "errors": {
    "": [
      "The input was not valid."
    ],
    "Parents[0].Childs[0].Parent.Prop1": [
      "The Prop1 field is required."
    ],
    "Parents[0].Childs[0].Parent.Prop2": [
      "The Prop2 field is required."
    ],
    "Parents[0].Childs[0].Parent.Prop3": [
      "The Prop3 field is required."
    ],
    "Parents[0].Childs[1].Parent.Prop1": [
      "The Prop1 field is required."
    ],
    "Parents[0].Childs[1].Parent.Prop2": [
      "The Prop2 field is required."
    ],
    "Parents[0].Childs[1].Parent.Prop3": [
      "The Prop3 field is required."
    ],
...

The Main-Class:

    public class Parent
    {
        public int ID { get; set; }

        
        [Required(AllowEmptyStrings = false)]
        public string Prop1{ get; set; } = string.Empty;

        
        [Required(AllowEmptyStrings = false)]
        public string Prop2 { get; set; } = string.Empty;

        
        [Required(AllowEmptyStrings = false)]
        public string Prop3 { get; set; } = string.Empty;

        
        public List<Child> Childs{ get; set; } = new();
    }

The Child-Class:

    public class Child
    {        
        public int Id { get; set; }

        [JsonIgnore] 
        public Parent Parent { get; set; } = new();

        [Required]
        public int ChildProp { get; set; }
       
    }

Is the [Required] Attribute of a Child higher-Prior than a [JsonIgnore] in the Parent? How can I fix that? Removing the Required Annotations is not a Option because I neet them for my UI.

I tried to use the different Conditions of the JsonIgnore with no effect.


Solution

  • I found a solution. Making the getter of the Parent-Property internal will do the trick.

    public class Child
    {        
        public int Id { get; set; }
    
        [JsonIgnore] 
        public Parent Parent { internal get; set; } = new();
    
        [Required]
        public int ChildProp { get; set; }
       
    }
    

    Thanks again for AVTUNEY for showing me custom json converters. With a little extra effort, the problem could certainly have been solved this way.