Search code examples
c#jsonazure-functions

Array properties not mapped/deserialized when deserializing JSON


I have a webservice that outputs this (abbreviated for question) json:

{
   "totalSize":401,
   "pageSize":250,
   "totalPages":2,
   "currentPage":1,
   "version":{
      "obsoleteDate":null,
      "resourceVersion":"2021-03-29"
   },
   "messages":[
     {},
     {},   
   ],
   "_embedded":[
      {
         "id": "dfsdf"
   }]
}

I defined the following class in my code:

 public class PagedResponse<T>
 {
         /// <summary>
     /// The total number of items
     /// </summary>
     public int TotalSize { get; set; } = 0;

     /// <summary>
     /// The number of items on a page
     /// </summary>
     public int PageSize { get; set; } = 0;

     /// <summary>
     /// The total number of pages
     /// </summary>
     public int TotalPages { get; set; } = 0;

     /// <summary>
     /// The number of the page in this response
     /// </summary>
     [JsonPropertyName("currentPage")]
     public int CurrentPage { get; set; } = 0;

     [JsonPropertyName("version")]
     public Version Version { get; set; } = new Version();

     [JsonPropertyName("messages")]
     public List<Message> Messages = new List<Message> { };

     [JsonPropertyName("_embedded")]
     [JsonProperty(PropertyName = "_embedded")]
     public List<T> Embedded = new List<T>();

     public PagedResponse() { }
 }

when using jsonconvert from newtonsoft.json. This deserialized perfectly fine. Embedded has the list of items from the json.

When I try the same with the serializer from system.text.json, Both messages and Embedded are left empty. The direct properties like totalpages are given the correct value and the same for the Version property.

Deserialized like this:

PagedResponse<Employee>? response = await dataResponse.Content.ReadFromJsonAsync<PagedResponse<Employee>>(new JsonSerializerOptions() { 
    PropertyNameCaseInsensitive = true
    //,UnmappedMemberHandling = System.Text.Json.Serialization.JsonUnmappedMemberHandling.Disallow
});

when I turn on UnmappedMemberHandling = System.Text.Json.Serialization.JsonUnmappedMemberHandling.Disallow. Then I get the error that Messages could not be mapped. But newtonsoft maps is perfectly fine even without an extra jsonproperty attribute.

What am I missing? Did I find some weakness in system.text.json or did I make some stupid mistake?

Edit: somebody associated this question with another question: "How to use class fields with System.Text.Json.JsonSerializer". That question is totally irrelevant. I was asking why some properties did not get values after deserialisation. The answer was because I accidentely made them field instead of properties. I don't care about deserializing to fields and know how to enable that. I just didn't see my error. An if I hadn't seen it eventually somebody would have answered, because you forgot to make them into properties.


Solution

  • Figured it out. Both Embedded and messages are fields in the code I posted and not properties. The default for system.text.json is to ignore fields. You can use jsonserializersettings to turn setting fields on, but I just correct my mistake and made both into properties.