Web API 2 : 객체 및 해당 하위 객체에서 camelCased 속성 이름과 함께 JSON을 반환하는 방법


104

최신 정보

모든 답변에 감사드립니다. 저는 새 프로젝트를 진행 중이며 마침내이 문제를 해결 한 것 같습니다. 실제로 다음 코드가 원인이 된 것 같습니다.

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

WebAPI가 아니라고 가정하고 무해한 JsonContent를 간과했습니다.

이것은 어디에서나 사용됩니다 ... 내가 처음으로 말할 수 있습니까, 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(); 

Mayank의 답변 : CamelCase JSON WebAPI 하위 개체 (중첩 된 개체, 하위 개체) 는 만족스럽지 않지만 linq2sql을 사용하면서 이러한 속성을 생성 된 코드에 추가해야한다는 것을 깨달을 때까지 실행 가능한 대답처럼 보였습니다.

이 작업을 자동으로 수행하는 방법이 있습니까? 이 '더러운'은 오랫동안 나를 괴롭 혔습니다.



또한 Linq2SQL이 부분 클래스를 생성하는 이유가 있습니다. 또한 ... Linq2SQL WTF ?!
Aron 2015

1
감사합니다.하지만이 링크는 MVC 용이며, 제가 사용하고있는 Web API 2이고, 이와 같이 콘텐츠 유형을 설정하고 문자열을 반환하는 방법이 있는지 확실하지 않지만있는 경우 보이지 않습니다. 아주 옳은 솔루션처럼 .. 부분 클래스에 대한 팁도 감사하지만 부분의 다른 부분에 정의 된 속성에 속성을 추가 할 수 있습니까?
Tom

또한 예, linq2sql wtf ... 내 결정이 아닙니다. :)
Tom

결과는 동일하며 유일한 차이점은 JsonSerializer. stackoverflow.com/questions/13274625/…
Aron 2015

답변:


175

모두 합치면 얻을 수 있습니다 ...

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

확실히 켜는 방법은 있지만 내 문제는이 설정이 무시되었다는 것이 었습니다 (내 답변 참조)
Tom

1
@Tom 음 ... Tom은 무엇을 알고 json.UseDataContractJsonSerializer = true;있습니까? WebAPI Json.Net에 직렬화 를 사용하지 않도록 지시 합니다. > _ <
Aron

예, 지금합니다. 그러나 또 다른 문제가있었습니다. 나는 이것을 확인했다. 내 대답을 참조하십시오. 또한 stackoverflow.com/questions/28552567/…을
Tom

1
사실, 면밀히 살펴보면 이전 결론에서 내가 잘못되었다는 것이 밝혀졌습니다. 내 업데이트를 참조하십시오.

28

이것은 나를 위해 일한 것입니다.

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

클래스 CamelCasePropertyNamesContractResolverJson.NET 라이브러리 Newtonsoft.Json.dll에서 제공됩니다 .


3
이 접근 방식은 응용 프로그램의 모든 API가 아닌 일부 API에 대해서만 camelCasing을 사용하려는 경우 매우 유용합니다. (Y)
droidbot

15

그것은 밝혀졌다

return Json(result);

범인이어서 직렬화 프로세스가 camelcase 설정을 무시하도록했습니다. 그리고

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

제가 찾고 있던 드로이드였습니다.

또한

json.UseDataContractJsonSerializer = true;

스패너를 작업에 넣었고 내가 찾고 있던 드로이드가 아닌 것으로 판명되었습니다.


이것은 실제로 잘못된 대답입니다. 질문에서 내 업데이트를 참조하십시오.
Tom

나는 실제로 이것이 사실임을 발견했습니다. 를 반환 할 때 Json(result)PascalCase에서 모든 것을보고 있었지만 반환했을 때 Content(StatusCode, result)예상대로 작동했습니다.
DeeKayy90

12

위의 모든 답변은 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);
    }

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

주요 차이점은 GlobalConfiguration.Configuration이 아닌 new HttpConfiguration ()입니다.


OWIN을 통한 자체 호스팅의 경우 이것은 완벽합니다. 감사!
Julian Melville 2015 년

3
Owin을 사용하는 경우이 솔루션은 완벽하게 작동하지만 머리카락을 모두 찢은 후에 만 ​​가능합니다!
Alastair

10

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 작업 메서드가 다음과 같은 방식으로 데이터를 반환하는지 확인하고 최신 버전의 Json.Net/Newtonsoft.Json을 설치했는지 확인합니다.

    [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에서 다음 줄을 추가하십시오.

 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

다음은 모호한 것입니다. route 속성이 GET URL과 일치하지 않지만 GET URL이 메소드 이름과 일치하면 jsonserializer camel case 지시문이 무시됩니다.

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

2

나는 다음과 같이 그것을 해결했다.

[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와 함께 WebApi를 사용하고 있으며 Breeze 컨트롤러에 대해 Breeze가 아닌 작업을 실행하려고 할 때 동일한 문제를 실행했습니다. apprach Request.GetConfiguration을 사용하려고 시도했지만 동일한 결과가 발생했습니다. 그래서 Request.GetConfiguration에 의해 반환 된 객체에 액세스 할 때 요청에 의해 사용되는 serializer가 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);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.