Search code examples
c#classdomain-driven-designjson-deserializationprivate-members

private set in deserialize json doens't set correctly


I have this class as you see :

public class UserScope
    {
        public List<Guid> testCenterIds { get; private set; }
        public List<Guid> roleIds { get; private set; }
        public List<int> townCodes { get; private set; }
        public List<int> CityCodes { get; private set; }
        public List<int> provinceCodes { get; private set; }
        public List<string> provinceCodes2 { get; private set; }

        public UserScope(List<Guid> testCenterIds, List<Guid> roleIds, List<int> townIds, List<int> cityIds, List<int> provinceIds, List<string> provinceIds2)
        {
            this.testCenterIds = testCenterIds;
            this.roleIds = roleIds;
            this.townCodes = townIds;
            this.CityCodes = cityIds;
            this.provinceCodes = provinceIds;
            this.provinceCodes2 = provinceIds2;
        }
    }

When I want to convert my json to model as you can see :

  static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");
        var uc = new UserScope(
   new List<Guid> { Guid.NewGuid(), Guid.NewGuid() },
      new List<Guid> { Guid.NewGuid(), Guid.NewGuid() },
      new List<int> { 12126 },
      new List<int> { 12122 },
      new List<int> { 12312, 13479 }, new List<string> { "12312", "13479" }

  );
        var jsons = Newtonsoft.Json.JsonConvert.SerializeObject(uc);

        var jsond = Newtonsoft.Json.JsonConvert.DeserializeObject<UserScope>(jsons);
    }

JsonConvert can't convert townCodes ,CityCodes,provinceCodes ,provinceCodes2 and initializes them,In final townCodes ,CityCodes,provinceCodes ,provinceCodes2 are null.But testCenterIds,roleIds work fine.why?


Solution

  • Your UserScope only have one constructor which accepts certain arguments (no default constructor with no arguments), and no properties are marked with JsonProperty, so JSON.NET assumes it needs to call that constructor to create an instance. It then matches keys from json string with names of arguments of that constructor. testCenterIds and roleIds names do match said keys, while other argument names do not, so JSON.NET pass nulls there instead. If you rename constructor arguments like this:

    public UserScope(List<Guid> testCenterIds, List<Guid> roleIds, List<int> townCodes, List<int> cityCodes, List<int> provinceCodes, List<string> provinceCodes2)
    {
        this.testCenterIds = testCenterIds;
        this.roleIds = roleIds;
        this.townCodes = townCodes;
        this.CityCodes = cityCodes;
        this.provinceCodes = provinceCodes;
        this.provinceCodes2 = provinceCodes2;
    }
    

    Then they all will be populated. Alternatively you can mark all properties with JsonProperty attribute (good to always do that if possible and suitable) as mentioned in answer linked in comments.