.NET ReadFromJsonAsync() throws JsonException when API response contains wrapper object

2 weeks ago 17
ARTICLE AD BOX

Solution would depend if other endpoints also use a wrapper.

If all endpoints use the wrapper, I would define it in your code and use it in repo

public class ApiResopnseWrapper<T> { public List<T> Data { get; set; } public string Message { get; set; } public bool IsSuccess { get; set; } }

And change your method to use this class instead:

public async Task<IDataResult<List<T>>> GetListAsync(string endpoint, Expression<Func<T, bool>>? filter = null) { ... var wrapper = await response.Content.ReadFromJsonAsync<ApiResopnseWrapper<T>>(); var data = wrapper.Data; ... }

But if the API is not returning all responses in a wrapper (some come as raw list), then you need further tweaks.

If you know what endpoints return a wrapper and which ones are not, you could handle it by adding some flag to your method:

public async Task<IDataResult<List<T>>> GetListAsync( string endpoint, bool hasWrapper, Expression<Func<T, bool>>? filter = null) { ... var wrapper = hasWrapper ? (await response.Content.ReadFromJsonAsync<ApiResopnseWrapper<T>>()) .Data : await response.Content.ReadFromJsonAsync<List<T>>(); var data = wrapper.Data; ... }

Yet another option is that you have complete no knowledge what API could return, this might change without your control and you want to bulletproof your implementation, then I would define following helper:

private static List<T> GetDataAsync<T>(HttpResponseMessage response, CancellationToken cancellationToken) { try { return await response.Content.ReadFromJsonAsync<List<T>>(); } catch (JsonException ex) { return (await response.Content.ReadFromJsonAsync<ApiResopnseWrapper<T>>()) .Data; } }

and then use it in your method:

public async Task<IDataResult<List<T>>> GetListAsync(string endpoint, Expression<Func<T, bool>>? filter = null) { ... var data = await GetDataAsync(response, cancellationToken: default); ... }

PS My suggestion also is to use arrays instead of wrappers around it, such as List, unless you need features exposed by the type, that array does not have. However I usually find myself and my coworkers to overuse List everywhere, while it's not needed most of the times.

Read Entire Article