从ASP.NET MVC中的Json()强制使用小写属性名称

Jam*_*hes 80 asp.net-mvc json

鉴于以下课程,

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

    public string Message { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我在这样的Controller动作中返回其中一个,

return Json(new Result() { Success = true, Message = "test"})
Run Code Online (Sandbox Code Playgroud)

但是,我的客户端框架期望这些属性是小写的成功和消息.没有实际上必须有小写的属性名称是一种方法来实现这个思想正常的Json函数调用?

Jam*_*hes 127

实现此目的的方法是实现JsonResult类似这样的自定义: 使用自定义JsonResult创建自定义ValueType和Serialising (原始链接已死).

并使用替代的序列化程序,如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() 
    }
);
Run Code Online (Sandbox Code Playgroud)

结果是

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


dav*_*v_i 12

如果您使用Web API,更改序列化程序很简单,但不幸的是MVC本身使用JavaScriptSerializer没有选项来更改它以使用JSON.Net.

詹姆斯的回答丹尼尔的答案给了你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" }
Run Code Online (Sandbox Code Playgroud)

您甚至可以将其设置为自动应用于所有操作(仅支持性能的轻微性能is):

FilterConfig.cs

// ...
filters.Add(new JsonNetFilterAttribute());
Run Code Online (Sandbox Code Playgroud)

代码

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*iel 9

使用我的解决方案,您可以重命名所需的每个属性.

我在这里和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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

所以在我的控制器中,我可以做到这一点

        return new JsonNetResult(result);
Run Code Online (Sandbox Code Playgroud)

在我的模型中,我现在可以:

    [JsonProperty(PropertyName = "n")]
    public string Name { get; set; }
Run Code Online (Sandbox Code Playgroud)

请注意,现在,您必须设置JsonPropertyAttribute要序列化的每个属性.