ASP.NET MVC의 Json ()에서 소문자 속성 이름 강제 적용


89

다음 클래스가 주어지면

public class Result
{      
    public bool Success { get; set; }

    public string Message { get; set; }
}

컨트롤러 작업에서이 중 하나를 반환합니다.

return Json(new Result() { Success = true, Message = "test"})

그러나 내 클라이언트 측 프레임 워크는 이러한 속성이 소문자 성공 및 메시지가 될 것으로 예상합니다. 실제로 소문자 속성 이름을 가질 필요없이 정상적인 Json 함수 호출을 생각할 수있는 방법입니까?

답변:


130

이를 달성하는 방법은 JsonResult다음과 같은 사용자 지정을 구현하는 것입니다. 사용자 지정 ValueType 생성 및 사용자 지정 JsonResult (원본 링크 사용 중지)로 직렬화 .

그리고 이러한 종류의 동작을 지원하는 JSON.NET 과 같은 대체 직렬화기를 사용합니다 . 예 :

Product product = new Product
{
  ExpiryDate = new DateTime(2010, 12, 20, 18, 1, 0, DateTimeKind.Utc),
  Name = "Widget",
  Price = 9.99m,
  Sizes = new[] {"Small", "Medium", "Large"}
};

string json = 
  JsonConvert.SerializeObject(
    product,
    Formatting.Indented,
    new JsonSerializerSettings 
    { 
      ContractResolver = new CamelCasePropertyNamesContractResolver() 
    }
);

결과

{
  "name": "Widget",
  "expiryDate": "\/Date(1292868060000)\/",
  "price": 9.99,
  "sizes": [
    "Small",
    "Medium",
    "Large"
  ]
}


JSON.NET을 사용하고 있고 camelCase가 아니라 snake_case를 원한다면이 요점을 확인하십시오. 정말 도움이되었습니다! gist.github.com/crallen/9238178
Niclas Lindqvist

역 직렬화하려면 어떻게합니까? 전의. "small"에서 "Small"로
rook

1
현대 JSON.NET의 버전 @NiclasLindqvist는 GET snake_case에 훨씬 간단한 방법이 있습니다 : newtonsoft.com/json/help/html/NamingStrategySnakeCase.htm
소렌 Boisen

17

Web API를 사용하는 경우 serializer를 변경하는 것은 간단하지만 안타깝게도 MVC 자체는 JavaScriptSerializer옵션없이 JSON.Net을 사용하도록 변경합니다.

James의 대답Daniel의 대답 은 JSON.Net의 유연성을 제공하지만 일반적으로 수행하는 모든 곳 에서 큰 프로젝트가있는 경우 문제를 증명할 수 있고 다음과 같은 경우 매우 유연하지 않은 return Json(obj)것으로 변경 해야 함을 의미 return new JsonNetResult(obj)합니다. 사용하려는 직렬 변환기에 대한 마음이 바뀝니다.


나는 ActionFilter길 을 가기로 결정했다 . 아래 코드를 사용하면 JsonResultJSON.Net (소문자 속성 포함)을 사용하도록 속성을 적용 하여 모든 작업을 수행 할 수 있습니다 .

[JsonNetFilter]
[HttpPost]
public ActionResult SomeJson()
{
    return Json(new { Hello = "world" });
}

// outputs: { "hello": "world" }

모든 작업에 자동으로 적용되도록 설정할 수도 있습니다 ( is검사 의 사소한 성능 저하 만 있음 ).

FilterConfig.cs

// ...
filters.Add(new JsonNetFilterAttribute());

코드

public class JsonNetFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result is JsonResult == false)
            return;

        filterContext.Result = new CustomJsonResult((JsonResult)filterContext.Result);
    }

    private class CustomJsonResult : JsonResult
    {
        public CustomJsonResult(JsonResult jsonResult)
        {
            this.ContentEncoding = jsonResult.ContentEncoding;
            this.ContentType = jsonResult.ContentType;
            this.Data = jsonResult.Data;
            this.JsonRequestBehavior = jsonResult.JsonRequestBehavior;
            this.MaxJsonLength = jsonResult.MaxJsonLength;
            this.RecursionLimit = jsonResult.RecursionLimit;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");

            if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet
                && String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
                throw new InvalidOperationException("GET not allowed! Change JsonRequestBehavior to AllowGet.");

            var response = context.HttpContext.Response;

            response.ContentType = String.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;

            if (this.ContentEncoding != null)
                response.ContentEncoding = this.ContentEncoding;

            if (this.Data != null)
            {
                var json = JsonConvert.SerializeObject(
                    this.Data,
                    new JsonSerializerSettings
                        {
                            ContractResolver = new CamelCasePropertyNamesContractResolver()
                        });

                response.Write(json);
            }
        }
    }
}

10

내 솔루션을 사용하면 원하는 모든 속성의 이름을 바꿀 수 있습니다.

여기 와 SO 에서 솔루션의 일부를 찾았습니다.

public class JsonNetResult : ActionResult
    {
        public Encoding ContentEncoding { get; set; }
        public string ContentType { get; set; }
        public object Data { get; set; }

        public JsonSerializerSettings SerializerSettings { get; set; }
        public Formatting Formatting { get; set; }

        public JsonNetResult(object data, Formatting formatting)
            : this(data)
        {
            Formatting = formatting;
        }

        public JsonNetResult(object data):this()
        {
            Data = data;
        }

        public JsonNetResult()
        {
            Formatting = Formatting.None;
            SerializerSettings = new JsonSerializerSettings();
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            var response = context.HttpContext.Response;
            response.ContentType = !string.IsNullOrEmpty(ContentType)
              ? ContentType
              : "application/json";
            if (ContentEncoding != null)
                response.ContentEncoding = ContentEncoding;

            if (Data == null) return;

            var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
            var serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Serialize(writer, Data);
            writer.Flush();
        }
    }

컨트롤러에서 할 수 있도록

        return new JsonNetResult(result);

내 모델에서 이제 다음을 가질 수 있습니다.

    [JsonProperty(PropertyName = "n")]
    public string Name { get; set; }

이제 JsonPropertyAttribute직렬화하려는 모든 속성에을 설정해야 합니다.


1

오래된 질문이지만 아래 코드 스 니펫이 다른 사람들에게 도움이 될 것입니다.

MVC5 Web API로 아래에서 수행했습니다.

public JsonResult<Response> Post(Request request)
    {
        var response = new Response();

        //YOUR LOGIC IN THE METHOD
        //.......
        //.......

        return Json<Response>(response, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() });
    }

0

이 설정을에 추가 Global.asax할 수 있으며 모든 곳에서 작동합니다.

public class Global : HttpApplication
{   
    void Application_Start(object sender, EventArgs e)
    {
        //....
         JsonConvert.DefaultSettings = () =>
         {
             var settings = new JsonSerializerSettings
             {
                 ContractResolver = new CamelCasePropertyNamesContractResolver(),
                 PreserveReferencesHandling = PreserveReferencesHandling.None,
                 Formatting = Formatting.None
             };

             return settings;
         }; 
         //....
     }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.