Buộc tên thuộc tính chữ thường từ Json () trong ASP.NET MVC


89

Cho lớp sau,

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

    public string Message { get; set; }
}

Tôi đang trả lại một trong những điều này trong một hành động Bộ điều khiển như vậy,

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

Tuy nhiên, khuôn khổ phía khách hàng của tôi mong đợi các thuộc tính này thành công và thông điệp bằng chữ thường. Không cần thực sự phải có tên thuộc tính chữ thường, đó có phải là một cách để khắc phục suy nghĩ này khi gọi hàm Json thông thường?

Câu trả lời:


130

Cách để đạt được điều này là thực hiện một tùy chỉnh JsonResultnhư sau: Tạo ValueType tùy chỉnh và Serialising với JsonResult tùy chỉnh (liên kết gốc đã chết) .

Và sử dụng một trình tuần tự thay thế như JSON.NET , hỗ trợ loại hành vi này, ví dụ:

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() 
    }
);

Kết quả trong

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


Nếu bạn đang sử dụng JSON.NET và không muốn camelCase mà là solid_case, hãy xem ý chính này, thực sự đã giúp tôi! gist.github.com/crallen/9238178
Niclas Lindqvist

Làm cách nào để giải mã trên không? Ví dụ. từ "nhỏ" thành "Nhỏ"
rook

1
@NiclasLindqvist Đối với phiên bản JSON.NET hiện đại, có một cách đơn giản hơn nhiều để get snake_case: newtonsoft.com/json/help/html/NamingStrategySnakeCase.htm
Søren Boisen

17

Thay đổi bộ tuần tự rất đơn giản nếu bạn đang sử dụng API Web, nhưng tiếc là bản thân MVC sử dụng JavaScriptSerializermà không có tùy chọn nào để thay đổi điều này để sử dụng JSON.Net.

Câu trả lời của Jamescâu trả lời của Daniel cung cấp cho bạn sự linh hoạt của JSON.Net nhưng có nghĩa là ở mọi nơi mà bạn thường return Json(obj)phải thay đổi thành return new JsonNetResult(obj)hoặc tương tự mà nếu bạn có một dự án lớn có thể chứng minh một vấn đề và cũng không linh hoạt nếu bạn thay đổi ý định về bộ nối tiếp bạn muốn sử dụng.


Tôi đã quyết định đi xuống ActionFiltercon đường. Đoạn mã dưới đây cho phép bạn thực hiện bất kỳ hành động nào bằng cách sử dụng JsonResultvà chỉ cần áp dụng một thuộc tính cho nó để sử dụng JSON.Net (với các thuộc tính chữ thường):

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

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

Bạn thậm chí có thể thiết lập điều này để tự động áp dụng cho tất cả các hành động (chỉ với một lần truy cập hiệu suất nhỏ của một isséc):

FilterConfig.cs

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

Mật mã

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

Với giải pháp của tôi, bạn có thể đổi tên mọi tài sản mà bạn muốn.

Tôi đã tìm thấy một phần của giải pháp ở đây và trên 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();
        }
    }

Vì vậy, trong bộ điều khiển của tôi, tôi có thể làm điều đó

        return new JsonNetResult(result);

Trong mô hình của tôi, bây giờ tôi có thể có:

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

Lưu ý rằng bây giờ, bạn phải thiết lập JsonPropertyAttributemọi thuộc tính bạn muốn tuần tự hóa.


1

Mặc dù đó là một câu hỏi cũ, nhưng hy vọng đoạn mã dưới đây sẽ hữu ích cho những người khác,

Tôi đã làm bên dưới với API Web MVC5.

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

Bạn có thể thêm cài đặt này vào Global.asaxvà nó sẽ hoạt động ở mọi nơi.

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;
         }; 
         //....
     }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.