HttpClient ObjectContent JSON: 在 json 对象中使用根 class 名称的格式?
HttpClient ObjectContent JSON: format with root class name in json object?
我使用 json2csharp.com 为 json 源生成一个 C# class。我的 json 是:
{
"email_verified": true,
"user_id": "gg2323",
"app_metadata": {
"tc_app_user": {
"user_guid": "c0fb150f6er344df98ea3a06114e1e4a",
"cto_admin_a_user_id": "551294d4f6cfb46e65a5aq71",
"lang": "EN",
"country": "USA",
"disabled": false
}
我生成的 C# 是:
public class TcAppUser
{
public string user_guid { get; set; }
public string cto_admin_a_user_id { get; set; }
public string lang { get; set; }
public string country { get; set; }
public bool disabled { get; set; }
}
public class AppMetadata
{
public TcAppUser tc_app_user { get; set; }
public int logins_count { get; set; }
}
public class RootObject
{
public bool email_verified { get; set; }
public string user_id { get; set; }
public AppMetadata app_metadata { get; set; }
}
使用 .NET HttpClient GET,我可以很好地从 JSON API 读入此 C# 结构。走另一条路 (POST, PATCH) 会带来一个问题:当我使用如下常用方法时,我的 app_metadata 属性 名称在生成的 JSON 输出中被删除:
//Would be nice: var contentIn = new ObjectContent<string>(RootObjectInstance.app_metadata, new JsonMediaTypeFormatter());
string json = JsonConvert.SerializeObject(RootObjectInstance.app_metadata);
HttpResponseMessage response = await hclient.PatchAsync("api/users/" + user_id, new StringContent(json, Encoding.UTF8, "application/json"));
结果 JSON 现在是:
{
"tc_app_user": {
"lang": "en-en",
"country": "GER",
"disabled": false
}
}
我的快速技巧是使用以下附加包装器动态重新打包 app_metadata 属性,使其输出格式与输入格式相同。其余部分与上面相同:
dynamic wireFormatFix = new ExpandoObject();
wireFormatFix.app_metadata = usr.app_metadata;
string json = JsonConvert.SerializeObject(wireFormatFix);
现在我的 JSON 输出对应于 JSON 输入。 我的问题:实现对称 json 输入和输出的最佳实践是什么,而无需讨厌的格式修复?
编辑:如果我尝试修补整个结构(RootObjectInstance 而不是 RootObjecInstance.app_metadata),我得到:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Payload validation error: 'Additional properties not allowed: 'user_id'."
}
因此,我必须发送正确打包的 C# RootObject 的 app_metadata subset/property,或者我必须有选择地从 RootObject 中删除字段以满足 API 的要求.
谢谢!
正在从您的 JSON 中删除根 app_metadata
标记,因为您根本没有对其进行序列化。这个:
string json = JsonConvert.SerializeObject(RootObjectInstance.app_metadata);
将序列化里面的所有东西 app_metadata
.
如果序列化整个对象图,则不需要修补任何内容:
string json = JsonConvert.SerializeObject(RootObjectInstance);
作为旁注,您应该遵循 C# naming conventions。您可以使用 JsonProperty
来帮助您。
编辑:
好的,在你的编辑之后我看到了实际的问题。您在查询字符串中通过 user_id
调用了 API,并且您的对象内部也有一个 user_id
属性。这似乎需要两个不同的对象来完成这项工作。
您有两种可能性:
创建对象层次结构:
public class BaseObject
{
[JsonProperty(email_verified)]
public bool EmailVerified { get; set; }
[JsonProperty(app_metadata)]
public AppMetadata AppMetadata { get; set; }
}
public class ExtendedObject : BaseObject
{
[JsonProperty(user_id)]
public string UserId { get; set; }
}
然后使用基本类型序列化数据:
var baseObj = new BaseObject(); // Fill the object properties.
var json = JsonConvert.SerializeObject(intermidiateObj);
HttpResponseMessage response = await hclient.PatchAsync("api/users/" +
user_id,
new StringContent(json,
Encoding.UTF8,
"application/json"));
使用仅包含您实际需要的属性的匿名对象:
var intermidiateObj = new { app_metadata = usr.app_metadata };
var json = JsonConvert.SerializeObject(intermidiateObj);
HttpResponseMessage response = await hclient.PatchAsync("api/users/" +
user_id,
new StringContent(json,
Encoding.UTF8,
"application/json"));
我使用 json2csharp.com 为 json 源生成一个 C# class。我的 json 是:
{
"email_verified": true,
"user_id": "gg2323",
"app_metadata": {
"tc_app_user": {
"user_guid": "c0fb150f6er344df98ea3a06114e1e4a",
"cto_admin_a_user_id": "551294d4f6cfb46e65a5aq71",
"lang": "EN",
"country": "USA",
"disabled": false
}
我生成的 C# 是:
public class TcAppUser
{
public string user_guid { get; set; }
public string cto_admin_a_user_id { get; set; }
public string lang { get; set; }
public string country { get; set; }
public bool disabled { get; set; }
}
public class AppMetadata
{
public TcAppUser tc_app_user { get; set; }
public int logins_count { get; set; }
}
public class RootObject
{
public bool email_verified { get; set; }
public string user_id { get; set; }
public AppMetadata app_metadata { get; set; }
}
使用 .NET HttpClient GET,我可以很好地从 JSON API 读入此 C# 结构。走另一条路 (POST, PATCH) 会带来一个问题:当我使用如下常用方法时,我的 app_metadata 属性 名称在生成的 JSON 输出中被删除:
//Would be nice: var contentIn = new ObjectContent<string>(RootObjectInstance.app_metadata, new JsonMediaTypeFormatter());
string json = JsonConvert.SerializeObject(RootObjectInstance.app_metadata);
HttpResponseMessage response = await hclient.PatchAsync("api/users/" + user_id, new StringContent(json, Encoding.UTF8, "application/json"));
结果 JSON 现在是:
{
"tc_app_user": {
"lang": "en-en",
"country": "GER",
"disabled": false
}
}
我的快速技巧是使用以下附加包装器动态重新打包 app_metadata 属性,使其输出格式与输入格式相同。其余部分与上面相同:
dynamic wireFormatFix = new ExpandoObject();
wireFormatFix.app_metadata = usr.app_metadata;
string json = JsonConvert.SerializeObject(wireFormatFix);
现在我的 JSON 输出对应于 JSON 输入。 我的问题:实现对称 json 输入和输出的最佳实践是什么,而无需讨厌的格式修复?
编辑:如果我尝试修补整个结构(RootObjectInstance 而不是 RootObjecInstance.app_metadata),我得到:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Payload validation error: 'Additional properties not allowed: 'user_id'."
}
因此,我必须发送正确打包的 C# RootObject 的 app_metadata subset/property,或者我必须有选择地从 RootObject 中删除字段以满足 API 的要求.
谢谢!
正在从您的 JSON 中删除根 app_metadata
标记,因为您根本没有对其进行序列化。这个:
string json = JsonConvert.SerializeObject(RootObjectInstance.app_metadata);
将序列化里面的所有东西 app_metadata
.
如果序列化整个对象图,则不需要修补任何内容:
string json = JsonConvert.SerializeObject(RootObjectInstance);
作为旁注,您应该遵循 C# naming conventions。您可以使用 JsonProperty
来帮助您。
编辑:
好的,在你的编辑之后我看到了实际的问题。您在查询字符串中通过 user_id
调用了 API,并且您的对象内部也有一个 user_id
属性。这似乎需要两个不同的对象来完成这项工作。
您有两种可能性:
创建对象层次结构:
public class BaseObject { [JsonProperty(email_verified)] public bool EmailVerified { get; set; } [JsonProperty(app_metadata)] public AppMetadata AppMetadata { get; set; } } public class ExtendedObject : BaseObject { [JsonProperty(user_id)] public string UserId { get; set; } }
然后使用基本类型序列化数据:
var baseObj = new BaseObject(); // Fill the object properties.
var json = JsonConvert.SerializeObject(intermidiateObj);
HttpResponseMessage response = await hclient.PatchAsync("api/users/" +
user_id,
new StringContent(json,
Encoding.UTF8,
"application/json"));
使用仅包含您实际需要的属性的匿名对象:
var intermidiateObj = new { app_metadata = usr.app_metadata }; var json = JsonConvert.SerializeObject(intermidiateObj); HttpResponseMessage response = await hclient.PatchAsync("api/users/" + user_id, new StringContent(json, Encoding.UTF8, "application/json"));