Web API 2: nesnelerde ve alt nesnelerinde camelCased özellik adlarıyla JSON nasıl döndürülür?


104

GÜNCELLEME

Tüm cevaplar için teşekkürler. Yeni bir projedeyim ve görünüşe göre sonunda bunun altına inmişim: Görünüşe göre şu kod aslında suçluydu:

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

başka yerde ...

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

WebAPI olduğunu ancak hayır olduğunu varsayarak zararsız görünen JsonContent'i gözden kaçırmıştım.

Bu her yerde kullanılıyor ... İlk söyleyen ben olabilir miyim, wtf? Veya belki de "Bunu neden yapıyorlar?"


orijinal soru takip eder

Bunun basit bir yapılandırma ayarı olacağı düşünülürdü, ancak artık çok uzun süredir benden kaçtı.

Çeşitli çözümlere ve cevaplara baktım:

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

en son WebAPI sürümü için geçerli görünmüyor ...

Aşağıdakiler işe yaramıyor gibi görünüyor - özellik adları hala PascalCased.

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;

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

json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

Mayank'ın cevabı: CamelCase JSON WebAPI Alt Nesneleri (İç içe geçmiş nesneler, alt nesneler) tatmin edici görünmüyordu, ancak bu özniteliklerin linq2sql kullandığımız için oluşturulan koda eklenmesi gerektiğini anlayana kadar uygulanabilir bir cevap gibi görünüyordu ...

Bunu otomatik olarak yapmanın bir yolu var mı? Bu "iğrenç" uzun zamandır beni rahatsız ediyor.



Ayrıca Linq2SQL'in kısmi sınıflar üretmesinin bir nedeni vardır. Ayrıca ... Linq2SQL WTF ?!
Aron

1
Teşekkürler ama bu bağlantı MVC için, kullanıyorum Web API 2 ve içerik türünü bu şekilde ayarlayıp bir dize döndürmenin bir yolu olup olmadığından emin değilim, ancak varsa görünmüyor tıpkı doğru çözüm gibi .. Kısmi sınıflarla ilgili ipucu için de teşekkürler, ancak parçanın diğer kısmında tanımlanan bir özelliğe bir nitelik eklemek mümkün müdür?
Tom

Ayrıca evet, linq2sql wtf ... benim kararım değil :)
Tom

sonuç aynı, tek fark, enjekte ettiğiniz yer JsonSerializer. stackoverflow.com/questions/13274625/…
Aron

Yanıtlar:


175

Hepsini bir araya koyarsan ...

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

Kesinlikle açmanın yolu, ancak benim sorunum bu ayarın yok sayılmasıydı (
Tom

1
@Tom erm ... Tom ne yaptığını biliyor muydun json.UseDataContractJsonSerializer = true;? WebAPI'ye Json.Netserileştirme için kullanmamasını söyler . > _ <
Aron

Evet, şimdi yapıyorum. Ancak ek bir sorun da vardı. Bunu doğruladım. Cevabımı gör. Ayrıca stackoverflow.com/questions/28552567/…
Tom

1
Aslında, daha yakından incelendiğinde, önceki sonucumda yanıldığım ortaya çıktı. Güncellememe bakın.
Tom

28

Bu benim için çalıştı:

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

Ve sonra:

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

Sınıf , Json.NET kitaplığından CamelCasePropertyNamesContractResolvergelir .Newtonsoft.Json.dll


3
Bu yaklaşım, camelCasing'e uygulamadaki tüm API'ler için değil, yalnızca bazı API'ler için sahip olmak istendiğinde çok kullanışlıdır. (Y)
droidbot

15

Şekline dönüştü

return Json(result);

suçluydu ve seri hale getirme sürecinin deve harfleri ayarını yok saymasına neden oldu. Ve şu

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

aradığım droid.

Ayrıca

json.UseDataContractJsonSerializer = true;

Çalışmalara bir anahtar koyuyordum ve aradığım droid olmadığı ortaya çıktı.


Bu aslında yanlış cevap. Güncellememi soruda görün.
Tom

Aslında bunun böyle olduğunu buldum. Döndüğümde Json(result), PascalCase'deki her şeyi görüyordum, ancak geri döndüğümde Content(StatusCode, result)beklendiği gibi çalıştı.
DeeKayy90

12

Yukarıdaki yanıtların tümü, Owin Hosting ve Ninject ile benim için işe yaramadı. İşte benim için çalıştı:

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

Temel fark şudur: GlobalConfiguration.Configuration yerine new HttpConfiguration ().


OWIN aracılığıyla kendi kendine barındırma için bu mükemmel. Teşekkürler!
Julian Melville

3
Owin kullanıyorsanız, bu çözüm mükemmel çalışır, ancak ancak tüm saçınızı yırttıktan sonra!
Alastair

10

WebApiConfig Kodu:

    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 Eylem Yönteminizin verileri aşağıdaki şekilde döndürdüğünden ve Json.Net/Newtonsoft.Json'ın en son sürümünü yüklediğinizden emin olun:

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

4

Owin Startup'ınıza bu satırı ekleyin ...

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

3

Burada belirsiz bir tane var, rota özniteliği GET url ile eşleşmediğinde ancak GET url'si yöntem adıyla eşleştiğinde, jsonserializer camel durum yönergesi göz ardı edilir, ör.

http: // web sitesi / 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();
}

2

Bunu aşağıdaki yollarla çözdüm.

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

0

Breeze ile WebApi kullanıyorum ve esinti olmayan bir eylemi bir esinti denetleyicisine yürütmeye çalışırken aynı sorunu yaşadım. Apprach Request.GetConfiguration'ı kullanmayı denedim ama aynı sonuç. Bu yüzden, Request.GetConfiguration tarafından döndürülen nesneye eriştiğimde, istek tarafından kullanılan serileştiricinin, esinti sunucusunun sihir yapmak için kullandığı seri hale getirici olduğunu anlıyorum. Herhangi bir şekilde, farklı bir HttpConfiguration oluşturarak sorunumu çözdüm:

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

ve aşağıdaki gibi Request.CreateResponse'de parametre olarak iletmek:

return this.Request.CreateResponse(HttpStatusCode.OK, result, WebApiHelper.BreezeControllerCamelCase);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.