Biorąc pod uwagę następującą klasę,
public class Result
{
public bool Success { get; set; }
public string Message { get; set; }
}
Zwracam jeden z nich w takiej akcji kontrolera,
return Json(new Result() { Success = true, Message = "test"})
Jednak moja struktura po stronie klienta oczekuje, że te właściwości będą sukcesem i komunikatem małymi literami. Bez faktycznej konieczności posiadania nazw właściwości pisanych małymi literami, czy jest to sposób na osiągnięcie tej myśli w normalnym wywołaniu funkcji Json?
asp.net-mvc
json
James Hughes
źródło
źródło
Zmiana serializatora jest prosta, jeśli używasz interfejsu API sieci Web, ale niestety samo MVC używa
JavaScriptSerializer
bez opcji zmiany tego, aby używać JSON.Net.Odpowiedź Jamesa i odpowiedź Daniela zapewniają elastyczność JSON.Net, ale oznaczają, że wszędzie tam, gdzie normalnie byś to zrobił
return Json(obj)
, musisz zmienić nareturn new JsonNetResult(obj)
lub coś podobnego, co w przypadku dużego projektu może okazać się problemem, a także nie jest zbyt elastyczne, jeśli zmienisz zdanie na temat serializatora, którego chcesz użyć.Postanowiłem pójść tą
ActionFilter
trasą. Poniższy kod umożliwia wykonanie dowolnej akcji przy użyciuJsonResult
i po prostu zastosowanie do niego atrybutu, aby użyć JSON.Net (z właściwościami małych liter):[JsonNetFilter] [HttpPost] public ActionResult SomeJson() { return Json(new { Hello = "world" }); } // outputs: { "hello": "world" }
Możesz nawet ustawić to tak, aby automagicznie stosowało się do wszystkich akcji (z tylko niewielkim uderzeniem wydajnościowym podczas
is
czeku):FilterConfig.cs
// ... filters.Add(new JsonNetFilterAttribute());
Kod
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); } } } }
źródło
Dzięki mojemu rozwiązaniu możesz zmienić nazwę każdej nieruchomości, którą chcesz.
Znalazłem część rozwiązania tutaj i na 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(); } }
Więc w moim kontrolerze mogę to zrobić
return new JsonNetResult(result);
W moim modelu mogę teraz mieć:
[JsonProperty(PropertyName = "n")] public string Name { get; set; }
Zauważ, że teraz musisz ustawić na
JsonPropertyAttribute
każdą właściwość, którą chcesz serializować.źródło
Chociaż to stare pytanie, mam nadzieję, że poniższy fragment kodu będzie pomocny dla innych,
Zrobiłem poniżej z 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() }); }
źródło
Możesz dodać to ustawienie do
Global.asax
i będzie działać wszędzie.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; }; //.... } }
źródło