【问题标题】:CamelCase JSON WebAPI Sub-Objects (Nested objects, child objects)CamelCase JSON WebAPI 子对象(嵌套对象、子对象)
【发布时间】:2014-06-15 17:49:25
【问题描述】:

我正在创建一个复杂对象,其中包含要从我的 Web api 控制器返回的子对象(嵌套对象)。该对象包含其他对象类型的列表。列表中的这些子对象类型遵循 .NET 中使用的帕斯卡大小写。

var persons = peopleLookup.Values;
var users = userLookup.Values;
var roles = rolesLookup.Values;
var groups = groupLookup.Values;
var roleAssignments = roleAssignmentLookup.Values;
var groupMembers = groupMemberLookup.Values;
return new { persons, users, roles, roleAssignments, groups, groupMembers };

我的问题是 WebAPI 不会对子项目的每个属性进行驼峰式大小写。例如,persons 列表中的第一个人应该具有 id、name 的属性,而不是 .NET pascal 大小写的 Id、Name。这同样适用于所有其他子项目。

【问题讨论】:

  • 我也有同样的问题。你弄明白了吗?

标签: c# json asp.net-web-api camelcasing pascalcasing


【解决方案1】:

您可以配置 JSON.NET 以在应用程序启动时生成驼峰式名称。来自Scott Allen's post的代码sn-p:

var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。我正在返回一个用于网格填充的对象。它具有一些属性,如行、页、总计等。将合同解析器设置为驼峰式案例可以解决顶层属性的问题。但是,如果任何属性包含属性名称为 pascal 大小写的对象列表,它不会改变它们的大小写。

    这就是我为解决这个问题所做的工作。

    带有要返回的数据的网格对象

    [DataContract]
    public class GridProperties<T>
    {
        [DataMember]
        public List<T> Rows { get; set; }
    
        [DataMember]
        public int Records { get; set; }
    
        [DataMember]
        public int Total { get; set; }
    
        [DataMember]
        public int Page { get; set; }
    }
    

    Here Rows 保存对象列表。在这里,我返回了模型对象列表。模型类看起来像:

    public class ClientListModel
    {
        [DataMember(Name = "clientId")]
        public int ClientId { get; set; }
    
        [DataMember(Name = "firstName")]
        public string FirstName { get; set; }
    
        [DataMember(Name = "lastName")]
        public string LastName { get; set; }
    
        [DataMember(Name = "startDate")]
        public DateTime? StartDate { get; set; }
    
        [DataMember(Name = "status")]
        public string Status { get; set; }
    
        public ClientListModel()
        {}
    }
    

    下面是我如何从我的 API 控制器返回 JSON 数据

        [HttpGet]
        public GridProperties<ClientListModel> GetClients(int page)
        {
            const int rowsToDisplay = 10;
            try
            {
                IEnumerable<ClientListModel> clientList = null;
    
                using (var context = new AngularModelConnection())
                {
                    clientList = context.Clients.Select(i => new ClientListModel()
                    {
                        ClientId = i.Id,
                        FirstName = i.FirstName,
                        LastName = i.LastName,
                        StartDate = i.StartDate,
                        Status = (i.DischargeDate == null || i.DischargeDate > DateTime.Now) ? "Active" : "Discharged"
                        });
    
                        int total = clientList.Count(); //Get count of total records
                        int totalPages = Convert.ToInt16(Math.Ceiling((decimal) total/rowsToDisplay)); //Get total page of records
    
                        return new GridProperties<ClientListModel>
                        {
                            Rows = clientList.Skip((page - 1)*rows).Take(rows).ToList(),
                            Records = total,
                            Total = totalPages,
                            Page = page
                        };
                    }
                }
                catch (Exception exc)
                {
                    ExceptionLogger.LogException(exc);
                    return new GridProperties<ClientListModel>
                    {
                        Rows = null,
                        Records = 0,
                        Total = 0,
                        Page = page
                    };
                }
            }
    

    [DataMember(Name ="")] 属性指定当对象被序列化时该属性使用什么名称。

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      在尝试从 WebAPI 返回具有关系的 DataSet 时,我遇到了与嵌套对象类似的问题。使用ExpandoObject 对我有用,也许这会对你有所帮助。

      private static object ConvertDataSetWithRelationsToCamelCaseObject(DataSet ds)
              {
                  foreach (DataRelation relation in ds.Relations)
                  {
                      relation.Nested = true;
                  }
      
                  var doc = new XmlDocument();
                  doc.LoadXml(ds.GetXml());
                  var pascalCaseJson = JsonConvert.SerializeXmlNode(doc, Formatting.None, true);
                  var pascalCaseObject = JsonConvert.DeserializeObject<ExpandoObject>(pascalCaseJson);
                  var camelCaseJson = JsonConvert.SerializeObject(pascalCaseObject, Formatting.Indented,
                      new JsonSerializerSettings {ContractResolver = new CamelCasePropertyNamesContractResolver(),});
                  return JsonConvert.DeserializeObject(camelCaseJson);
              }
      

      使用关系创建数据集的示例代码:

      var dsTasks = new Tasks().Find(sqlParameters);
      var dsValidators = new Validators().Find(sqlParameters);
      var dsProperties = new ValidatorProperties().Find(sqlParameters);
      
      dsTasks.Tables[0].TableName = "Tasks";
      dsValidators.Tables[0].TableName = "Validators";
      dsProperties.Tables[0].TableName = "ValidatorProperties";
      
      var ds = new DataSet {DataSetName = "ValidatorsByTask"};
      ds.Tables.Add(dsTasks.Tables[0].Copy());
      ds.Tables.Add(dsValidators.Tables[0].Copy());
      ds.Tables.Add(dsProperties.Tables[0].Copy());
      
      ds.Relations.Add("Task_Validators", ds.Tables["Tasks"].Columns["Id"], ds.Tables["Validators"].Columns["TaskId"]);
      ds.Relations.Add("Validator_Properties", ds.Tables["Validators"].Columns["Id"], ds.Tables["ValidatorProperties"].Columns["ValidatorId"]);
      
      var data = ConvertDataSetWithRelationsToCamelCaseObject(ds);
      

      【讨论】:

        【解决方案4】:

        在 CamelCase 与默认的 .NET 的 PascalCase 中格式化 JSON 输出的简短且非常简单的解决方案。

        将以下两行添加到您的 WebApiConfig.cs 文件(在 WebApi 2 的 App_Start 文件夹下):

        // Get the default json formatter 
        var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
        
        // Switch from PascalCase to CamelCase
        jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-08
          • 1970-01-01
          • 1970-01-01
          • 2015-08-23
          • 2015-11-29
          • 1970-01-01
          • 2016-12-13
          • 2021-10-06
          相关资源
          最近更新 更多