HttpClient ObjectContent JSON:json对象中具有根类名的格式?

时间:2015-05-07 08:30:23

标签: c# json httpclient

我使用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的要求。

谢谢!

1 个答案:

答案 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属性。这似乎需要两个不同的对象。

您有几种可能性:

  1. 创建对象层次结构:

    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; }
    }
    
  2. 然后使用基类型序列化数据:

    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"));
    
    1. 使用仅包含您实际需要的属性的匿名对象:

      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"));