Search code examples
jsonasp.net-coredeserializationodata

System.Text.Json.JsonException: The JSON value could not be converted to enum


I have an ASP.NET Core OData Web API with an endpoint that returns the following:

{
    "@odata.context": "https://localhost:44305/odata/$metadata#OrgUnits",
    "@odata.count": 3,
    "value": [
        {
            "Status": "Active",
            "OperationMode": "Normal",
            "BaseUrl": "https://test.nl/",
            "OrgUnitCode": "TEST",
            "Name": "Test",
            "Address": "Spoorlaan 348",
            "PostalCode": "5038 CC",
            "City": "Tilburg",
            "PhoneNumber": "012 345 6789",
            "ChamberOfCommerceNumber": null,
            "ContactName": null,
            "Website": null,
            "EmailAddress": null,
            "Id": 1,
            "DateCreated": "0001-01-01T00:00:00Z",
            "LastModifiedDate": "0001-01-01T00:00:00Z"
        },

Status and OperationMode are enums:

    public enum OperationMode
    {
        Inherited = 0,
        Normal = 1,
        Test = 2
    }
    public enum Status
    {
        Inherited = 0,
        Active = 1,
        Inactive = 2
    }
    public class OrgUnit : BaseEntity
    {
        public Status Status { get; set; }
        
        public OperationMode OperationMode { get; set; }
        
        public string BaseUrl { get; set; }
        
        public string OrgUnitCode { get; set; }
        
        public string Name { get; set; }
        
        public string Address { get; set; }
        
        public string PostalCode { get; set; }
        
        public string City { get; set; }
        
        public string PhoneNumber { get; set; }
        
        public string ChamberOfCommerceNumber { get; set; }
        
        public string ContactName { get; set; }
        
        public string Website { get; set; }
        
        public string EmailAddress { get; set; }
    }

On my frontend, a Blazor Server application, I deserialize the response body into an OrgUnitsResponse object. This response object will be used to fill a Telerik Grid component.

        public async Task<OrgUnitsResponse> GetOrgUnits(DataSourceRequest request)
        {
            var baseUrl = "https://localhost:44305/odata/OrgUnits?";

            var requestUrl = $"{baseUrl}{request.ToODataString()}";

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUrl);
            requestMessage.Headers.Add("Accept", "application/json");
            var client = HttpClient.CreateClient();
            var response = await client.SendAsync(requestMessage);

            if (response.IsSuccessStatusCode)
            {
                var body = await response.Content.ReadAsStringAsync();
                var oDataResponse = JsonSerializer.Deserialize<OrgUnitsResponse>(body);
                return oDataResponse;
            }
            else
            {
                throw new HttpRequestException(
                    "Request failed. I need better error handling, e.g., returning empty data.");
            }
        }
    public class OrgUnitsResponse
    {
        [System.Text.Json.Serialization.JsonPropertyName("value")]
        public List<OrgUnit> OrgUnits { get; set; }
        
        [System.Text.Json.Serialization.JsonPropertyName("@odata.count")]
        public int Total { get; set; }
    }

Sadly, this doesn't seem to work. I get the following error:

System.Text.Json.JsonException: The JSON value could not be converted to Domain.Enums.Status. Path: $.value[0].Status 

How can I correctly deserialize the JSON string values into enums?


Solution

  • Already figured out the answer 1 minute after asking this question. Leaving it up there so anyone else experiencing this issue can read this.

    The solution is passing a JsonStringEnumConverter as an option to the serializer.

    var options = new JsonSerializerOptions();
    options.Converters.Add(new JsonStringEnumConverter());
    var oDataResponse = JsonSerializer.Deserialize<OrgUnitsResponse>(body, options);
    

    Please also note that when using a JsonSerializerOptions class you may also need to specify a JsonSerializerDefaults option:

    var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);