System.Text.Json 从 API 调用反序列化嵌套对象 - 数据包装在父 JSON 属性中 [英] System.Text.Json Deserialize nested object from API call - Data is wrapped in parent JSON property

查看:25
本文介绍了System.Text.Json 从 API 调用反序列化嵌套对象 - 数据包装在父 JSON 属性中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 API JSON 响应,它将数据内容包装在 data 属性中,如下所示:

I have an API JSON response that wraps the data content in a data property, which looks like this:

{ 
   "data":{ 
      "email":"admin@example.com",
      "mobile":"+1555555123",
      "id":4,
      "first_name":"Merchant",
      "last_name":"Vendor",
      "role":"Merchant",
   }
}

因此,当使用像 RequestSharp 这样的库请求用户对象时,response.Content 将用户的内容包装在 data json 属性,因为它来自 API.代码:

So when making request for a User Object with a Library like RequestSharp, the response.Content has the content for the User wrapped in the data json property as it comes from the API. Code:

var request = RequestHelper.CreateTokenRequest(email, password); // Create the request from a helper
var client = new RestClient(BaseUrl); // create new RestSharp Client
IRestResponse response = client.Execute(request); // execute the request
var content = response.Content; // raw content as string

这很好,但是当我使用 System.Text.Json 将 json 反序列化为对象时,如下所示,将创建 User 对象,但会不分配任何属性,尽管这是预期的,因为序列化程序正在寻找具有 first_namelast_name 的属性......而不是 ['data']['first_name']

This is fine, but when I go to deserialize the json to an Object with System.Text.Json, like the following, will create the User object but will not assign any of the attributes, although this is sort of expected because the serializer is looking for properties with first_name and last_name... not ['data']['first_name']

User account = JsonSerializer.Deserialize<User>(response.Content, options);

如何让 JsonSerializer.Deserialize 忽略 data 包装器?在其他 API 调用中,它可能是对象的名称,例如 transactionuser,无论哪种方式,它都会包装数据.

How can I get the JsonSerializer.Deserialize to ignore the data wrapper? In other API calls it may be the name of the Object such as transaction or user, either way, it wraps the data.

其他注意事项:

我的目标是最新的 .Net Core 3.1 并从 Newtonsoft Json.Net 迁移

I am targeting the latest .Net Core 3.1 and am migrating from Newtonsoft Json.Net

我的用户对象:

using System.ComponentModel;
using System.Text.Json.Serialization;

namespace MyApplication.Models
{
    public interface IUser
    {
        string FirstName { get; set; }
        string LastName { get; set; }
        string Email { get; set; }
        string Mobile { get; set; }
        string Id { get; set; }
        string Role { get; set; }
    }

    public class User : IUser
    {
        [JsonPropertyName("first_name")]
        public string FirstName { get; set; }

        [JsonPropertyName("last_name")]
        public string LastName { get; set; }

        [JsonPropertyName("email")]
        public string Email { get; set; }

        [JsonPropertyName("mobile")]
        public string Mobile { get; set; }

        [JsonPropertyName("id")]
        public string Id { get; set; }

        [JsonPropertyName("role")]
        public string Role { get; set; }

        [JsonIgnore]
        public string Token { get; set; }
    }
}

<小时>

解决后更新:


Update after resolution:

我从下面的 u/Nikunj Kakadiya 中选择了一个可行的答案,并且与我最终所做的最相似.

I selected the answer from u/Nikunj Kakadiya below as something that would work and was most similar to what I ended up doing.

我创建了一个基于通用模板的容器类来处理这样的data:

I created a generic template based container class to handle the data like this:

public class Container<T>
{
    [JsonPropertyName("data")]
    public T Data { get; set; }
}

然后我使用该容器类来包装从 API 调用返回的 json 内容,如下所示:

I then used that container class to wrap the returned json contents from the API call, like this:

var options = new JsonSerializerOptions
{
    AllowTrailingCommas = true
};

Container<User> accountContainer = JsonSerializer.Deserialize<Container<User>>(response.Content, options);
User account = accountContainer.Data;

此外,正如 u/Pavel Anikhouski 所指出的,我对 User 类的序列化导致了一个错误,需要我为 id 字段创建一个自定义转换器.API 将 id 作为整数返回,尽管它是 User 类中的字符串.这是我遇到的最初令人困惑的错误,但我很快就弄清楚了:<代码>错误:JSON 值无法转换为 System.String.路径:$.data.id |行号:0 |BytePositionInLine:77.

Additionally, as u/Pavel Anikhouski noted, my serialization of the User class led to an error that required me to create a custom converter for the id field. The API returns the id as an integer although it is a string in the User class. This was the error I ran into which was initially confusing but I was able to figure out pretty quickly: ERROR: The JSON value could not be converted to System.String. Path: $.data.id | LineNumber: 0 | BytePositionInLine: 77.

这是自定义转换器IntToStringConverter:

public class IntToStringConverter : JsonConverter<string>
{
    public override string Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options) => reader.GetInt32().ToString();

    public override void Write(
        Utf8JsonWriter writer,
        string value,
        JsonSerializerOptions options) =>
        writer.WriteStringValue(value);
}

然后将 User 类更改为使用客户转换器:

and then changed the User Class to use the customer converter:

...
    [JsonPropertyName("id")]
    [JsonConverter(typeof(IntToStringConverter))]
    public string Id { get; set; }
...

推荐答案

您需要再创建一个类.这是下面给出的

You need to make one another class. That is given below

Public class UserData
{
    public User data { get; set; }; 
}

现在您可以使用名为 UserData 的新类反序列化数据,如下所示

Now you can Deserialize data using new class called UserData like below

UserData account = JsonSerializer.Deserialize<UserData>(response.Content, options);

这篇关于System.Text.Json 从 API 调用反序列化嵌套对象 - 数据包装在父 JSON 属性中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆