【问题标题】:JSON - Generic deserialization based on object typeJSON - 基于对象类型的通用反序列化
【发布时间】:2021-09-22 17:40:59
【问题描述】:

我正在尝试实现一个通用 HTTP 服务,该服务根据传递给该方法的对象类型来执行对我的 OData API 的请求。例如:如果我传递一个Employee类型的对象,它将检索所有员工,如果我传递一个Customer类型的对象,它将检索所有客户。

这是一个返回所有员工列表的示例 API 响应:

{
    "@odata.context": "https://localhost:44375/odata/$metadata#Employees",
    "@odata.count": 3,
    "value": [
        {
            "EmployeeType": "Manager",
            "FirstName": "Test",
            "LastName": "Test",
            "Address": "Test",
            "PostalCode": "1234AB",
            "City": "Test",
            "PhoneNumber": "0641615077",
            "EmailAddress": "test@test.nl",
            "HostelId": 1,
            "Id": 1,
            "DateCreated": "0001-01-01T00:00:00Z",
            "LastModifiedDate": "0001-01-01T00:00:00Z"
        },
        ...
     ]
}

我想将计数和值反序列化为一个名为 EntityListResponse 的对象。

    public class EntityListResponse
    {
        [System.Text.Json.Serialization.JsonPropertyName("value")]
        public List<object> Records { get; set; }
        
        [System.Text.Json.Serialization.JsonPropertyName("@odata.count")]
        public int Total { get; set; }
    }

我已经构建了自己的 Blazor 组件,它接收任何类型的对象作为参数:

    [Parameter]
    public TItem Entity { get; set; }

该组件有一个名为“ReadEntity”的方法,它调用我的通用 HTTP 服务。 OData 请求需要第一个参数,第二个参数是对象 - 例如 Employee。

    private async Task ReadEntity(GridReadEventArgs args)
    {
        var data = await _entityService.GetAll(args.Request, Entity);

        ...
    }

HTTP服务中的GetAll方法:

        public async Task<EntityListResponse> GetAll(DataSourceRequest request, object entity)
        {
            var baseUrl = $"{entity}s?";

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

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

            if (response.IsSuccessStatusCode)
            {
                var body = await response.Content.ReadAsStringAsync();

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

                return oDataResponse;
            }
            else
            {
                throw new HttpRequestException(
                    "Request failed. I need better error handling, e.g. returning empty data.");
            }
        }

除了反序列化之外,该方法中的所有内容都可以正常工作。问题是我不知道如何让反序列化器知道 EntityListResponse 的 Records 属性应该是哪种类型。现在它只是创建一个 JSON 对象列表:

我希望根据传递的对象类型来确定列表的对象类型。因此,如果我传递一个 Employee 类型的对象,它应该将响应主体反序列化为 List,如果我传递一个 Customer 类型的对象,它应该反序列化为 List,等等。

这甚至可以开始吗?

【问题讨论】:

  • 嗨,Brian,我决定看看你的包,但是在我的项目中安装它之后,它找不到包 - 使用语句说“无法解析符号 'BlazorOdataClient'”。我的项目使用 .NET 5 和 C# 9。
  • 我在那个包中使用.net 6 rc1

标签: c# json generics serialization blazor


【解决方案1】:

您可以使用它,但让您的方法改为接受泛型类型参数 (https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics)。

所以你的方法可能是这样的:

async Task<T> GET<T>(string endPoint).

那么当你要反序列化的时候,使用那里的 T。

var oDataResponse = JsonSerializer.Deserialize<T>(body, options);

【讨论】:

    【解决方案2】:

    使用通用类:

    public class OdataResponce<T>
    {
        [JsonPropertyName(name: "@odata.context")]
        public string ContextUrl { get; set; }
    
        [JsonPropertyName(name: "@odata.count")]
        public int Count { get; set; }
    
        [JsonPropertyName(name: "value")]
        public IEnumerable<T> Data { get; set; }
    }
    

    示例用法:

    var query = $"odata/{endPoint}?{queryString}&$top={top}&$skip={skip}&$count=true";
    var odataResponce = 
        await http.GetFromJsonAsync<OdataResponce<WeatherForecast>>(query);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 1970-01-01
      • 2016-01-11
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多