Search code examples
json.netgenericsenumsabstraction

Abstract generic custom result class with enum values in .NET Core (enum does not serialize)


Hello I tried to create two abstract classes,one class with Content and the other with Status so multiple project can inherit it and add their enum status and their content and use it for it own purpose. I am using .NET 5.0. I have the next code.

public enum EnumValues { Success,Fail}


public abstract class EnumStatus<TEnum> where TEnum : System.Enum
{
    public TEnum Status { get; set; }
    protected EnumStatus(TEnum status)
    {
        Status = status;
    }
}

public abstract class Result<T> : EnumStatus<System.Enum>
{
    public T Content { get; set; }
    
    protected Result(System.Enum status) : base(status)
    {

    }

    protected Result(T content, System.Enum status) : base(status)
    {
        Content = content;
    }
   
}

and I have my custom result class that is

public class CustomResult<T> : Result<T>
{
    public CustomResult(System.Enum status) : base(status)
    {
    }

    public CustomResult(T content, System.Enum status) : base(content, status)
    {
        
    }

    public static implicit operator CustomResult<T>(T content)
    {
        return new CustomResult<T>(content, EnumValues.Success);
    }

    public static implicit operator CustomResult<T>(EnumValues status)
    {
        return new CustomResult<T>(status);
    }

}

So when I use it in my controller

public async Task<IActionResult> Test()
{
      return new JsonResult(new CustomResult<bool>(true,EnumValues.Success));
}

The response I get in my postman call is

{
"content": true,
"status": {}
}

The content is always returned but my status is always empty, debugging it the content and status are valid and correct set in the constructor but when it is returned to client the status is always empty, but if I return the result with the implicit operator e.g

return Ok(EnumValues.Success)

it return valid result. Can someone explain to me why is this happening like that? is there any solution about this ? or I am making some stupid mistake


Solution

  • the easiest way to fix it , would be using Newtonsoft.Json. Add this code to startup

    using Newtonsoft.Json.Serialization;
    
    services.AddControllers()
    .AddNewtonsoftJson(options =>
      options.SerializerSettings.ContractResolver =
            new CamelCasePropertyNamesContractResolver());
    

    if you want to continue with Text.Json

    services.AddControllers()
    .AddJsonOptions(options =>
    new JsonSerializerOptions
    {
        Converters = { new JsonStringEnumConverter() },
        WriteIndented = true,
    });
    
    var options = new JsonSerializerOptions
        {
            Converters = { new JsonStringEnumConverter() },
            WriteIndented = true,
        };
    var json = System.Text.Json.JsonSerializer.Serialize(result, options);
         
    var obj = System.Text.Json.JsonSerializer.Deserialize<CustomResult<bool,EnumValues>>(json,options);
    

    and fix classess

    public abstract class Result<T,TEnum> : EnumStatus<TEnum> where TEnum : Enum
    {
        public T Content { get; set; }
    
        protected Result(TEnum status) : base(status)
        {
    
        }
    
        protected Result(T content, TEnum status) : base(status)
        {
            Content = content;
        }
    
        
    }
    
    
    public class CustomResult<T,TEnum> : Result<T,TEnum>  where TEnum : Enum
    {
        
        public CustomResult(TEnum status) : base(status)
        {
        }
        [System.Text.Json.Serialization.JsonConstructorAttribute]
        public CustomResult(T content, TEnum status) : base(content, status)
        {
    
        }
    }