作者:冬季梅花1991_156 | 来源:互联网 | 2023-09-24 11:37
我有一个API JSON响应,它将数据内容包装在data
属性中,如下所示:
{
"data":{
"email":"admin@example.com","mobile":"+1555555123","id":4,"first_name":"Merchant","last_name":"Vendor","role":"Merchant",}
}
因此,当使用诸如RequestSharp
之类的库请求用户对象时,response.Content
会将来自API的用户内容包装在data
json属性中。代码:
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_name
和last_name
而不是['data']['first_name']
寻找属性
User account = JsonSerializer.Deserialize(response.Content,options);
如何获取JsonSerializer.Deserialize
来忽略data
包装器?在其他API调用中,它可能是对象的名称,例如transaction
或user
,无论哪种方式,它都会包装数据。
其他说明:
我的目标是最新的.Net Core 3.1,并且正在从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; }
}
}
解决后更新:
我从下面的u / Nikunj Kakadiya中选择了答案,因为它是可行的,并且与我最终所做的最相似。
我创建了一个基于通用模板的容器类来处理data
,如下所示:
public class Container
{
[JsonPropertyName("data")]
public T Data { get; set; }
}
然后我使用该容器类包装从API调用返回的json内容,如下所示:
var optiOns= new JsonSerializerOptions
{
AllowTrailingCommas = true
};
Container accountCOntainer= JsonSerializer.Deserialize>(response.Content,options);
User account = accountContainer.Data;
此外,正如u / Pavel Anikhouski指出的那样,我对User
类的序列化导致了一个错误,该错误要求我为id
字段创建自定义转换器。尽管API是id
类中的字符串,但API会将User
作为整数返回。这是我最初遇到的错误,但是我很快就知道了:ERROR: The JSON value could not be converted to System.String. Path: $.data.id | LineNumber: 0 | BytePositionInLine: 77.
这是自定义转换器IntToStringConverter
:
public class IntToStringConverter : JsonConverter
{
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
类更改为使用客户转换器:
...
[JsonPropertyName("id")]
[JsonConverter(typeof(IntToStringConverter))]
public string Id { get; set; }
...
您需要再上一堂课。如下
Public class UserData
{
public User data { get; set; };
}
现在,您可以使用名为UserData的新类对数据进行反序列化
UserData account = JsonSerializer.Deserialize(response.Content,options);
,
可以使用User
API来获得System.Text.Json
对象,而无需从JSON示例中指定属性名称data
{
"data":{
"email":"admin@example.com","mobile":"+1555555123","id":4,"first_name":"Merchant","last_name":"Vendor","role":"Merchant",}
}
通过以下代码
var document = JsonDocument.Parse(json,new JsonDocumentOptions { AllowTrailingCommas = true });
var enumerator = document.RootElement.EnumerateObject();
if (enumerator.MoveNext())
{
var userJson = enumerator.Current.Value.GetRawText();
var user = JsonSerializer.Deserialize(userJson,new JsonSerializerOptions {AllowTrailingCommas = true});
}
在加载JsonDocument
上方的示例中,将枚举RootElement
以获取第一个嵌套对象作为文本以反序列化为User
实例。
通过名称获取document.RootElement.GetProperty("data");
之类的属性更容易,但是根据您的问题,名称实际上可以不同。也无法通过indexer进行访问,例如document.RootElement[0]
,因为它仅在元素的ValueKind
是Array
而不是Object
时才起作用,例如情况
我也将"id":4,
更改为"id":"4",
,因为出现错误
无法获取令牌类型'Number'的值作为字符串。
,
您可以创建一个这样的对象:
public class Data
{
public string email { get; set; }
public string mobile { get; set; }
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string role { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
然后
var data = JsonSerializer.Deserialize(JsonData);
然后您可以访问如下数据:
RootObject.Data.email ;
RootObject.Data.first_name
此外,每当您需要将JSON字符串转换为C#POCO类时,都可以使用这样的工具:http://json2csharp.com/
,
您可以摆脱数据对象,也可以编写自定义json转换器。我建议更改发送的数据或直接使用它,因为您尝试执行的操作不是最佳做法。