System.Text.Json从API调用反序列化嵌套对象-数据包装在父JSON属性中 [英] System.Text.Json Deserialize nested object from API call - Data is wrapped in parent JSON property
问题描述
我有一个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屋!