Web API 2: Comment retourner JSON avec les noms de propriétés camelCased, sur les objets et leurs sous-objets

mise à JOUR

Merci pour toutes les réponses. Je suis sur un nouveau projet et il semble que j'ai enfin le fond de l'histoire: Il semble que le code suivant est en fait à blâmer:

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

ailleurs...

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

j'avais négligé L'aspect inoffensif JsonContent en supposant qu'il était WebAPI mais non.

C'est utilisé partout ... Je peux être le premier à le dire, wtf? Ou peut-être qui doit être "Pourquoi font-ils cela?"


la question initiale suit

On aurait pensé que ce serait un simple paramètre de configuration, mais il m'a échappé depuis trop longtemps maintenant.

j'ai examiné diverses solutions et réponses:

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

ne semble pas s'appliquer à la dernière version WebAPI...

ce qui suit ne semble pas fonctionner - les noms de propriétés sont toujours PascalCased.

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;

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

json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

Mayank de réponse ici: CamelCase JSON WebAPI Sous-Objets (objets Imbriqués, les objets enfants) "1519290920 semblait un peu satisfaisante mais efficace de répondre jusqu'à ce que j'ai réalisé ces attributs doivent être ajoutés au code généré en utilisant linq2sql...

y a-t-il un moyen de faire ça automatiquement? Cette 'méchante' me tourmente depuis longtemps maintenant.

79
demandé sur Moes 2015-02-17 03:10:59

9 réponses

C'est tout ce que tu as...

protected void Application_Start()
{
    HttpConfiguration config = GlobalConfiguration.Configuration;
    config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;
}
147
répondu Aron 2016-07-26 03:32:09

C'est ce qui a fonctionné pour moi:

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

et ensuite:

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

la classe CamelCasePropertyNamesContractResolver vient de Newtonsoft.Json.dll dans Json.NET bibliothèque.

23
répondu felix-b 2015-02-17 07:27:57

toutes les réponses ci-dessus n'ont pas fonctionné pour moi avec Owin Hosting et Ninject. Voici ce qui a fonctionné pour moi:

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 différence clé est: nouvelle HttpConfiguration() plutôt que GlobalConfiguration.Configuration.

12
répondu mkaj 2015-08-11 20:24:24

il s'avère que

return Json(result);

est le coupable, ce qui fait que le processus de sérialisation ignore le paramètre camelcase. Et que

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

était le droïde que je cherchais.

aussi

json.UseDataContractJsonSerializer = true;

était en train de mettre une clé en main et s'est avéré ne pas être le droïde que je cherchais.

11
répondu Tom 2015-02-17 04:29:53

Code 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();

        }
    }



Assurez-vous que votre méthode D'action API retourne les données de la manière suivante et que vous avez installé la dernière version de Json.Net/Newtonsoft.Json installé:

    [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
répondu Jay Shah 2016-12-20 11:29:23

dans votre démarrage Owin ajouter cette ligne...

 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
répondu smatthews1999 2017-11-05 13:27:05

En voici un obscur, lorsque l'attribut route ne correspond pas à l'url GET mais que l'url GET correspond au nom de la méthode, la directive camel de jsonserializer serait ignorée par exemple

http://website/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
répondu jenson-button-event 2016-02-11 12:44:17

Je l'ai résolu en suivant les chemins.

[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<ItemInfo> itemList = GetItemsFromDatabase(moduleId);
                return Request.CreateResponse(HttpStatusCode.OK, itemList, config);
            }
            catch (System.Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
}
1
répondu Khademul Basher 2017-04-04 08:18:33

j'utilise WebApi avec Breeze et j'ai couru le même problème en essayant d'exécuter une action non-breeze dans un contrôleur breeze. J'ai essayé d'utiliser la requête d'apprach.GetConfiguration mais le même résultat. Donc, quand j'accède à l'objet retourné par demande.GetConfiguration je réalise que le serializer utilisé par request est celui que breeze-server utilise pour le rendre magique. De toute façon, j'ai résolu mon problème en créant une autre configuration Httpp:

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

et le passant comme paramètre à la Demande.CreateResponse comme suit:

return this.Request.CreateResponse(HttpStatusCode.OK, result, WebApiHelper.BreezeControllerCamelCase);
0
répondu Leonardo Neninger 2017-05-31 21:51:08