热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

System.Text.Json从API调用反序列化嵌套对象数据包装在父JSON属性中

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

我有一个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_namelast_name而不是['data']['first_name']

寻找属性

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

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

其他说明:

我的目标是最新的.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],因为它仅在元素的ValueKindArray而不是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转换器。我建议更改发送的数据或直接使用它,因为您尝试执行的操作不是最佳做法。


推荐阅读
author-avatar
冬季梅花1991_156
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有