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

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

问题描述


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

{ 
   "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

很好,但是当我去将json反序列化为对象时使用 System.Text.Json ,如下所示,将创建 User 对象,但不会分配任何属性,尽管这是预料之中的,因为序列化程序正在寻找具有 first_name last_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调用中,它可能是对象的名称,例如 transaction user ,无论哪种方式,它都会包装数据。

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.

我创建了一个基于通用模板的容器类来处理数据,如下所示:

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; }
...


推荐答案

上另一堂课。

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天全站免登陆