从 ASP.NET MVC 中的 Json() 强制小写属性名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2789593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Force lowercase property names from Json() in ASP.NET MVC
提问by James Hughes
Given the following class,
鉴于以下课程,
public class Result
{
public bool Success { get; set; }
public string Message { get; set; }
}
I am returning one of these in a Controller action like so,
我正在像这样在控制器操作中返回其中之一,
return Json(new Result() { Success = true, Message = "test"})
However my client side framework expects these properties to be lowercase success and message. Without actually having to have lowercase property names is that a way to acheive this thought the normal Json function call?
但是我的客户端框架希望这些属性是小写的成功和消息。实际上不必具有小写的属性名称是一种实现正常 Json 函数调用的想法的方法吗?
回答by James Hughes
The way to achieve this is to implement a custom JsonResultlike here:
Creating a custom ValueType and Serialising with a custom JsonResult(original link dead).
实现这一点的方法是实现一个JsonResult像这里的自定义:
Creating a custom ValueType and Serialising with a custom JsonResult (original link dead)。
And use an alternative serialiser such as JSON.NET, which supports this sort of behaviour, e.g.:
并使用支持此类行为的替代序列化程序,例如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()
}
);
Results in
结果是
{
"name": "Widget",
"expiryDate": "\/Date(1292868060000)\/",
"price": 9.99,
"sizes": [
"Small",
"Medium",
"Large"
]
}
回答by dav_i
Changing serializer is simple if you are using Web API, but unfortunately MVC itself uses JavaScriptSerializerwith no option to change this to use JSON.Net.
如果您使用的是 Web API,则更改序列化程序很简单,但不幸的是,MVC 本身JavaScriptSerializer无法将其更改为使用 JSON.Net。
James' answerand Daniel's answergive you the flexibility of JSON.Net but means that everywhere where you would normally do return Json(obj)you have to change to return new JsonNetResult(obj)or similar which if you have a big project could prove a problem, and also isn't very flexible if you change your mind on the serializer you want to use.
James 的回答和Daniel 的回答为您提供了 JSON.Net 的灵活性,但这意味着您通常return Json(obj)需要更改为return new JsonNetResult(obj)或类似的任何地方,如果您有一个大项目可能会证明存在问题,并且如果您改变了对要使用的序列化程序的想法。
I've decided to go down the ActionFilterroute. The below code allows you to take any action using JsonResultand simply apply an attribute to it to use JSON.Net (with lower case properties):
我决定走这ActionFilter条路。下面的代码允许您JsonResult使用 JSON.Net(具有小写属性)执行任何操作,只需将属性应用到它:
[JsonNetFilter]
[HttpPost]
public ActionResult SomeJson()
{
return Json(new { Hello = "world" });
}
// outputs: { "hello": "world" }
You can even set this up to automagically apply to all actions (with only the minor performance hit of an ischeck):
您甚至可以将其设置为自动应用于所有操作(检查时只有轻微的性能影响is):
FilterConfig.cs
过滤器配置文件
// ...
filters.Add(new JsonNetFilterAttribute());
The code
编码
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);
}
}
}
}
回答by Daniel
With my solution, you can rename every property you want.
使用我的解决方案,您可以重命名您想要的每个属性。
I've found part of the solution hereand on SO
我在这里和 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();
}
}
So that in my controller, I can do that
所以在我的控制器中,我可以做到这一点
return new JsonNetResult(result);
In my model, I can now have:
在我的模型中,我现在可以拥有:
[JsonProperty(PropertyName = "n")]
public string Name { get; set; }
Note that now, you have to set the JsonPropertyAttributeto every property you want to serialize.
请注意,现在,您必须将 设置为JsonPropertyAttribute要序列化的每个属性。
回答by pgcan
Though it is an old question, hope below code snippet will be helpful to others,
虽然这是一个老问题,但希望下面的代码片段对其他人有帮助,
I did below with MVC5 Web API.
我用 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() });
}
回答by Maksym Labutin
You can add this setting to Global.asax, and it will be work everywhere.
您可以将此设置添加到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;
};
//....
}
}

