다음 클래스가 주어지면
public class Result
{
public bool Success { get; set; }
public string Message { get; set; }
}
컨트롤러 작업에서이 중 하나를 반환합니다.
return Json(new Result() { Success = true, Message = "test"})
그러나 내 클라이언트 측 프레임 워크는 이러한 속성이 소문자 성공 및 메시지가 될 것으로 예상합니다. 실제로 소문자 속성 이름을 가질 필요없이 정상적인 Json 함수 호출을 생각할 수있는 방법입니까?
답변
이를 달성하는 방법은 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"
]
}
답변
Web API를 사용하는 경우 serializer를 변경하는 것은 간단하지만 안타깝게도 MVC 자체는 JavaScriptSerializer
옵션없이 JSON.Net을 사용하도록 변경합니다.
James의 대답 과 Daniel의 대답 은 JSON.Net의 유연성을 제공하지만 일반적으로 수행하는 모든 곳 에서 큰 프로젝트가있는 경우 문제를 증명할 수 있고 다음과 같은 경우 매우 유연하지 않은 return Json(obj)
것으로 변경 해야 함을 의미 return new JsonNetResult(obj)
합니다. 사용하려는 직렬 변환기에 대한 마음이 바뀝니다.
나는 ActionFilter
길 을 가기로 결정했다 . 아래 코드를 사용하면 JsonResult
JSON.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);
}
}
}
}
답변
내 솔루션을 사용하면 원하는 모든 속성의 이름을 바꿀 수 있습니다.
여기 와 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
직렬화하려는 모든 속성에을 설정해야 합니다.
답변
오래된 질문이지만 아래 코드 스 니펫이 다른 사람들에게 도움이 될 것입니다.
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() });
}
답변
이 설정을에 추가 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;
};
//....
}
}