Подобъекты CamelCase JSON WebAPI (вложенные объекты, дочерние объекты)
Я создаю сложный объект с дочерними объектами (вложенными объектами) для возврата из моего контроллера веб-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 не верблюжий случай каждого из свойств подпунктов. Например, у первого лица в списке лиц должны быть атрибуты id, name, а не.NET паскаль Id, Name. То же самое должно относиться ко всем другим подпунктам.
4 ответа
Вы можете настроить JSON.NET для создания имен верблюдов при запуске приложения. Фрагмент кода из поста Скотта Аллена:
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
У меня такая же проблема. Я возвращаю объект для сетки населения. У него есть некоторые свойства, такие как Rows, Page, Total и т. Д. Установка решателя контракта на верблюжий случай решает проблему свойств на верхнем уровне. Но если какое-либо свойство содержит список объектов с именами в Паскале, оно не меняет их регистр.
Итак, вот что я сделал, чтобы обойти проблему.
Сетка объект с данными для возврата
[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; }
}
Здесь 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()
{}
}
И ниже, как я возвратил данные JSON из моего контроллера API
[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 ="")]
Атрибут указывает, какое имя использовать для свойства при сериализации объекта.
Надеюсь это поможет!
У меня была похожая проблема с вложенными объектами при попытке вернуть DataSet с отношениями из WebAPI. Используя 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);
Краткое и очень простое решение для форматирования вывода JSON в CamelCase по сравнению с PascalCase по умолчанию.NET.
Добавьте в свой файл WebApiConfig.cs (в папке App_Start в WebApi 2) следующие две строки:
// Get the default json formatter
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
// Switch from PascalCase to CamelCase
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();