Pregunta Web API 2: cómo devolver JSON con nombres de propiedad camelCased, sobre objetos y sus subobjetos


ACTUALIZAR

Gracias por todas las respuestas. Estoy en un nuevo proyecto y parece que finalmente llegué al fondo de esto: parece que el siguiente código fue el culpable:

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

en otra parte...

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

Había pasado por alto el inofensivo aspecto de JsonContent asumiendo que era WebAPI pero no.

Esto es usado en todos lados... ¿Puedo ser el primero en decir, wtf? O tal vez debería ser "¿Por qué están haciendo esto?"


la pregunta original sigue

Uno hubiera pensado que esto sería una configuración de configuración simple, pero ahora me ha eludido por mucho tiempo.

He visto varias soluciones y respuestas:

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

no parece aplicarse a la última versión de WebAPI ...

Lo siguiente no parece funcionar: los nombres de propiedad todavía están PascalCased.

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;

json.UseDataContractJsonSerializer = true;
json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;

json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

La respuesta de Mayank aquí: CamelCase JSON WebAPI Sub-Objects (Objetos anidados, objetos secundarios) parecía una respuesta insatisfactoria pero viable hasta que me di cuenta de que estos atributos deberían agregarse al código generado ya que estamos usando linq2sql ...

¿Alguna forma de hacer esto automáticamente? Este 'desagradable' me ha plagado por un largo tiempo ahora.


75
2018-02-17 00:10


origen


Respuestas:


Poniendo todo junto, obtienes ...

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

141
2018-02-17 01:55



Esto es lo que funcionó para mí:

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

Y entonces:

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

La clase CamelCasePropertyNamesContractResolver viene de Newtonsoft.Json.dll en Json.NET biblioteca.


22
2018-02-17 07:27



Todas las respuestas anteriores no funcionaron para mí con Owin Hosting y Ninject. Esto es lo que funcionó para mí:

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

    /// <summary>
    /// Configure all JSON responses to have camel case property names.
    /// </summary>
    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();
    }
}

La diferencia clave es: nueva HttpConfiguration () en lugar de GlobalConfiguration.Configuration.


12
2017-08-11 20:24



Resulta que

return Json(result);

fue el culpable, causando que el proceso de serialización ignore la configuración de camelcase. Y eso

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

era el droide que estaba buscando.

también

json.UseDataContractJsonSerializer = true;

Estaba poniendo una llave inglesa en las obras y resultó que NO era el droide que estaba buscando.


11
2018-02-17 01:33



Código de 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();

        }
    }


Asegúrese de que su método de acción API devuelva datos de la siguiente manera y que haya instalado la última versión de Json.Net/Newtonsoft.Json instalada:

    [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);
        }
    }

6
2017-12-20 11:16



En su Inicio de Owin, agregue esta línea ...

 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;
    }
}

4
2017-11-05 13:27



Aquí hay uno oscuro, cuando el atributo de ruta no coincidía con la url GET pero la url GET coincidía con el nombre del método, la directiva jsonserializer camel case se ignoraría, p.

http: // sitio web / api / geo / geodata

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

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

3
2018-02-11 12:44