Search code examples
c#jsonserializationdeserialization

JsonConvert.DeserializeObject defaults to first Enum item


I have the following data object.

public class Response<T> where T : MyBaseDTO
    {
     public bool result
        {
            get; set;
        }

     public List<Message> messages
        {
            get; set;
        }
     public List<T> data 
        {
            get; set;
        }
}
     public class Message
        {      
            public Message(MessageTypeEnum type)
            {
                this.typeEnum = type;
            }
    
            public string type
            {
                get
                {
                    return typeEnum.ToString();
                }
         
            }
    
            public MessageTypeEnum typeEnum
            {
                get; set;
            }
          
           public int index
            {
                get; set;
            }
            
            public string field
            {
                get; set;
            }
            public string code
            {
                get; set;
            }
           public string message
             {
              get; set;
            }
           public string messageValue
            {
             get; set;
             }
        public enum MessageTypeEnum
        {
            WARNING,
            INFO,
            ERROR
        }

When I use RestSharp to call the API, the deserialized Data is null with following error(Content contains correct response in string):

" ErrorMessage "Each parameter in the deserialization constructor on type 'Response.Message' must bind to an object property or field on deserialization."

I found the following post and added empty constructor to my object.

Error: Each parameter in constructor must bind to an object property or field on deserialization

    public class Message
{
    public Message()
    {
    }
    public Message(MessageTypeEnum type)
    {
        this.typeEnum = type;
    }

    public string type
    {
        get
        {
            return typeEnum.ToString();
        }

    }

    public MessageTypeEnum typeEnum
    {
        get; set;
    }

    public int index
    {
        get; set;
    }

    public string field
    {
        get; set;
    }
    public string code
    {
        get; set;
    }
    public string message
        {
          get; set;
         }
   public string messageValue
         {
          get; set;
          }
    public enum MessageTypeEnum
    {
        WARNING,
        INFO,
        ERROR
    }

Added empty constructor resolved my issue with RestSharp. However I just noticed it failed some unit tests in my other project that uses Message Object.

Here is the code

using var reader = new StreamReader(result.ResponseMessage.Content.ReadAsStream());
body = reader.ReadToEnd();

Response<Test> responseObject = JsonConvert.DeserializeObject<Response<Test>>(body);

"body" looks like something below which is expected.

body    "{\"result\":true,\"messages\":[{\"type\":\"ERROR\",\"index\":0,\"field\":\"ID\",\"code\":\"MISSING-ID\",\"message\":\"The entry is incomplete.",\"messageValue\":null}],\"data\":[{\"....

However, after the deserialization, "Type" became WARNING instead ERROR and hence it failed the unit test.

Looks like it defaults to first one of the Enum.

public enum MessageTypeEnum
        {
            WARNING,
            INFO,
            ERROR
        }

Does anyone knows what's going on here and how to fix the issue?


Solution

  • since you have type as string too, you have to fix your Message costructor by adding attribute

        [JsonConstructor]
        public Message(MessageTypeEnum type)
        {
            this.typeEnum = type;
        }
    

    after this everything is working properly