Web API 2: как вернуть JSON с именами свойств camelCased, на объекты и их под-объекты

ОБНОВИТЬ

Спасибо за ответы на все вопросы. Я нахожусь в новом проекте, и похоже, что я, наконец, дошел до конца: похоже, что на самом деле виноват следующий код:

public static HttpResponseMessage GetHttpSuccessResponse(object response, HttpStatusCode code = HttpStatusCode.OK) { return new HttpResponseMessage() { StatusCode = code, Content = response != null ? new JsonContent(response) : null }; } 

в другом месте …

 public JsonContent(object obj) { var encoded = JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore } ); _value = JObject.Parse(encoded); Headers.ContentType = new MediaTypeHeaderValue("application/json"); } 

Я забыл безобидный JsonContent, предполагая, что это WebAPI, но нет.

Это используется везде … Могу ли я просто сказать первым, wtf? Или, может быть, это должно быть «Почему они это делают?»


исходный вопрос

Можно было бы подумать, что это будет простая настройка конфигурации, но она слишком долго ускользает от меня.

Я рассмотрел различные решения и ответы:

https://gist.github.com/rdingwall/2012642

похоже, не относится к последней версии WebAPI …

Следующие, похоже, не работают – имена свойств все еще PascalCased.

 var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter; json.UseDataContractJsonSerializer = true; json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

Ответ Майанка здесь: Sub-Objects CamelCase JSON WebAPI (вложенные объекты, дочерние объекты) казался неудовлетворительным, но работоспособным ответом, пока я не понял, что эти атрибуты должны быть добавлены в сгенерированный код, поскольку мы используем linq2sql …

Любой способ сделать это автоматически? Эта «противная» меня мучила уже давно.

Собирая все это вместе, вы получаете …

 protected void Application_Start() { HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false; } 

Это то, что сработало для меня:

 internal static class ViewHelpers { public static JsonSerializerSettings CamelCase { get { return new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; } } } 

А потом:

 [HttpGet] [Route("api/campaign/list")] public IHttpActionResult ListExistingCampaigns() { var domainResults = _campaignService.ListExistingCampaigns(); return Json(domainResults, ViewHelpers.CamelCase); } 

Класс CamelCasePropertyNamesContractResolver поступает из Newtonsoft.Json.dll в библиотеке Json.NET .

Все приведенные выше ответы не помогли мне с Owin Hosting и Ninject. Вот что сработало для меня:

 public partial class Startup { public void Configuration(IAppBuilder app) { // Get the ninject kernel from our IoC. var kernel = IoC.GetKernel(); var config = new HttpConfiguration(); // More config settings and OWIN middleware goes here. // Configure camel case json results. ConfigureCamelCase(config); // Use ninject middleware. app.UseNinjectMiddleware(() => kernel); // Use ninject web api. app.UseNinjectWebApi(config); } ///  /// Configure all JSON responses to have camel case property names. ///  private void ConfigureCamelCase(HttpConfiguration config) { var jsonFormatter = config.Formatters.JsonFormatter; // This next line is not required for it to work, but here for completeness - ignore data contracts. jsonFormatter.UseDataContractJsonSerializer = false; var settings = jsonFormatter.SerializerSettings; #if DEBUG // Pretty json for developers. settings.Formatting = Formatting.Indented; #else settings.Formatting = Formatting.None; #endif settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } } 

Ключевым отличием является новый HttpConfiguration (), а не GlobalConfiguration.Configuration.

Оказывается, что

 return Json(result); 

был виновником, в результате чего процесс сериализации игнорировал настройку камеры. И это

 return Request.CreateResponse(HttpStatusCode.OK, result, Request.GetConfiguration()); 

был дроидом, которого я искал.

Также

 json.UseDataContractJsonSerializer = true; 

Ставил гаечный ключ в работах и ​​оказался НЕ дроидом, которого я искал.

Код WebApiConfig:

  public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); //This line sets json serializer's ContractResolver to CamelCasePropertyNamesContractResolver, // so API will return json using camel case config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } } 

Убедитесь, что ваш API Action Method возвращает данные следующим образом, и вы установили последнюю версию Json.Net/Newtonsoft.Json Installed:

  [HttpGet] public HttpResponseMessage List() { try { var result = /*write code to fetch your result*/; return Request.CreateResponse(HttpStatusCode.OK, cruises); } catch (Exception ex) { return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); } } 

В своем Owin Startup добавьте эту строку …

  public class Startup { public void Configuration(IAppBuilder app) { var webApiConfiguration = ConfigureWebApi(); app.UseWebApi(webApiConfiguration); } private HttpConfiguration ConfigureWebApi() { var config = new HttpConfiguration(); // ADD THIS LINE HERE AND DONE config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); config.MapHttpAttributeRoutes(); return config; } } 

Вот неясный, когда атрибут маршрута не соответствует URL-адресу GET, но URL-адрес GET соответствует имени метода, директива case jsonserializer camel будет проигнорирована, например

Http: // сайт / апи / гео / геоданных

 //uppercase fail cakes [HttpGet] [Route("countries")] public async Task GeoData() { return await geoService.GetGeoData(); } //lowercase nomnomnom cakes [HttpGet] [Route("geodata")] public async Task GeoData() { return await geoService.GetGeoData(); } 

Я решил это следующими способами.

 [AllowAnonymous] [HttpGet()] public HttpResponseMessage GetAllItems(int moduleId) { HttpConfiguration config = new HttpConfiguration(); config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false; try { List itemList = GetItemsFromDatabase(moduleId); return Request.CreateResponse(HttpStatusCode.OK, itemList, config); } catch (System.Exception ex) { return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message); } } 

Я использую WebApi с Breeze, и я столкнулся с той же проблемой при попытке выполнить не-бриз-действие в controllerе Breeze. Я попытался использовать оценку Request.GetConfiguration, но тот же результат. Поэтому, когда я обращаюсь к объекту, возвращенному Request.GetConfiguration, я понимаю, что сериализатор, используемый по запросу, используется сервером breeze-server, чтобы сделать его магическим. В любом случае, я решил проблему, создав другую HttpConfiguration:

 public static HttpConfiguration BreezeControllerCamelCase { get { var config = new HttpConfiguration(); var jsonSerializerSettings = config.Formatters.JsonFormatter.SerializerSettings; jsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false; return config; } } 

и передавая его в качестве параметра в Request.CreateResponse следующим образом:

 return this.Request.CreateResponse(HttpStatusCode.OK, result, WebApiHelper.BreezeControllerCamelCase); 
  • Поиск конкретного JToken по имени в иерархии JObject
  • Сериализация нескольких свойств DateTime в одном classе с использованием разных форматов для каждого из них
  • Заставить JSON.NET включать миллисекунды при сериализации DateTime (даже если компонент ms равен нулю)
  • Удаление десериализации JSON в .NET-объект с использованием Newtonsoft (или LINQ to JSON, возможно?)
  • Как десериализовать дочерний объект с динамическими (числовыми) именами клавиш?
  • Как я могу десериализовать JSON для простого словаря в ASP.NET?
  • Как преобразовать escape-строку JSON в объект JSON?
  • Json.NET Отключить десериализацию в DateTime
  • JSON.Net выдает StackOverflowException при использовании
  • Как преобразовать массив Json в список объектов в c #
  • Как можно десериализовать дочерний объект с динамическими (числовыми) именами клавиш?
  • Давайте будем гением компьютера.