我使用json2csharp.com为json源生成一个C#类。我的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子集/属性,正确打包,或者必须有选择地从RootObject中删除字段以满足API的要求。
谢谢!
答案 0 :(得分:1)
正在从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"));