Làm cách nào tôi có thể trả về JSON của camelCase được tuần tự hóa bởi JSON.NET từ các phương thức của bộ điều khiển ASP.NET MVC?


246

Vấn đề của tôi là tôi muốn trả lại dữ liệu JSON của camelCase (trái ngược với dữ liệu JSON của PascalCase) thông qua các ActionResult từ các phương thức của bộ điều khiển ASP.NET MVC, được tuần tự hóa bởi JSON.NET .

Như một ví dụ, hãy xem xét lớp C # sau:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Theo mặc định, khi trả về một thể hiện của lớp này từ bộ điều khiển MVC dưới dạng JSON, nó sẽ được tuần tự hóa theo kiểu sau:

{
  "FirstName": "Joe",
  "LastName": "Public"
}

Tôi muốn nó được tuần tự hóa (bởi JSON.NET) như:

{
  "firstName": "Joe",
  "lastName": "Public"
}

Làm thế nào để tôi làm điều này?

Câu trả lời:


389

hoặc, chỉ cần đặt:

JsonConvert.SerializeObject(
    <YOUR OBJECT>, 
    new JsonSerializerSettings 
    { 
        ContractResolver = new CamelCasePropertyNamesContractResolver() 
    });

Ví dụ:

return new ContentResult
{
    ContentType = "application/json",
    Content = JsonConvert.SerializeObject(new { content = result, rows = dto }, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }),
    ContentEncoding = Encoding.UTF8
};

2
Điều này phức tạp hơn để sử dụng, vì bạn phải cấu hình ContentResult cho mỗi phương thức điều khiển.
aknuds1

2
Vâng tôi hiểu rằng câu trả lời của bạn là một giải pháp có thể sử dụng lại, quan điểm của tôi là làm cho nó rõ ràng hơn rằng đó chỉ là một tham số trên phương thức Nối tiếp.
WebDever 18/03/2016

1
Nếu bạn trả về JSON từ một Controllerphương thức, có lẽ bạn nên sử dụng một ApiController, trong trường hợp đó câu trả lời này hoạt động rất tốt.
Simon Hartcher

1
@SimonHartcher Hãy xem xét phạm vi của câu hỏi, không phải là trường hợp chung.
aknuds1

1
Kiểu nội dung hợp lệ cho JSON là application/json, không text/plain.
Fred

94

Tôi tìm thấy một giải pháp tuyệt vời cho vấn đề này trên blog của Mats Karlsson . Giải pháp là viết một lớp con của ActionResult để tuần tự hóa dữ liệu thông qua JSON.NET, định cấu hình lớp sau để tuân theo quy ước camelCase:

public class JsonCamelCaseResult : ActionResult
{
    public JsonCamelCaseResult(object data, JsonRequestBehavior jsonRequestBehavior)
    {
        Data = data;
        JsonRequestBehavior = jsonRequestBehavior;
    }

    public Encoding ContentEncoding { get; set; }

    public string ContentType { get; set; }

    public object Data { get; set; }

    public JsonRequestBehavior JsonRequestBehavior { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (JsonRequestBehavior == JsonRequestBehavior.DenyGet && String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
        }

        var response = context.HttpContext.Response;

        response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }
        if (Data == null)
            return;

        var jsonSerializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
        response.Write(JsonConvert.SerializeObject(Data, jsonSerializerSettings));
    }
}

Sau đó sử dụng lớp này như sau trong phương thức bộ điều khiển MVC của bạn:

public ActionResult GetPerson()
{
    return new JsonCamelCaseResult(new Person { FirstName = "Joe", LastName = "Public" }, JsonRequestBehavior.AllowGet)};
}

3
Câu trả lời hoàn hảo: sạch sẽ và có thể tái sử dụng! Cảm ơn bạn.
sander

1
Trong khi giải pháp này vẫn hoạt động. nhưng nó đã được đề nghị 4 năm trở lại. Chúng ta có một giải pháp tốt hơn?
SharpCoder

59

Đối với WebAPI , hãy xem liên kết này: http://odetocode.com/bloss/scott/archive/2013/03/25/asp-net-webapi-tip-3-camelcasing-json.aspx

Về cơ bản, thêm mã này vào Application_Start:

var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();

4
API web và MVC đã được hợp nhất trong ASP.NET 6
AlexFoxGill 14/08/2015

1
Liên kết để thuận tiện; thiết lập này chơi thực sự độc đáo với câu trả lời này: stackoverflow.com/a/26068063/398630 (câu hỏi khác nhau, nhưng tôi sử dụng chúng cùng nhau và liên kết này có thể cứu tôi và những người khác trong tương lai).
BrainSlugs83

37

Tôi nghĩ rằng đây là câu trả lời đơn giản mà bạn đang tìm kiếm. Đó là từ blog của Shawn Wildermuth :

// Add MVC services to the services container.
services.AddMvc()
  .AddJsonOptions(opts =>
  {
    opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
  });

2
Tôi xin lỗi, các bạn. Tôi đọc qua bài đăng này quá nhanh. Nó dành cho ASP.NET 5.
Quantium

8
Trớ trêu thay, tôi đến đây để tìm câu trả lời cho câu hỏi mà bạn đã trả lời ở đây, vì vậy trong khi đó không phải là câu trả lời cho câu hỏi của OP, dù sao nó cũng giúp tôi. Cảm ơn! :)
porcus

1
Tôi thứ hai những gì @porcus đã nói! Cảm ơn @Quantium!
Gromer

4
fyi Đối với ASP.NET Core 1.0, đó là vỏ lạc đà theo mặc định OOTB
Chris

3
Hóa ra đây không phải (chính xác) mặc định cho .NET Core 1.0. Giải pháp này ảnh hưởng đến các thuộc tính động và những thứ không bị ảnh hưởng theo mặc định. stackoverflow.com/questions/41329279/ cường
Niels Brinch

13

Một thay thế cho bộ lọc tùy chỉnh là tạo một phương thức mở rộng để tuần tự hóa bất kỳ đối tượng nào thành JSON.

public static class ObjectExtensions
{
    /// <summary>Serializes the object to a JSON string.</summary>
    /// <returns>A JSON string representation of the object.</returns>
    public static string ToJson(this object value)
    {
        var settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Converters = new List<JsonConverter> { new StringEnumConverter() }
        };

        return JsonConvert.SerializeObject(value, settings);
    }
}

Sau đó gọi nó khi trở về từ hành động điều khiển.

return Content(person.ToJson(), "application/json");

Thanh lịch và đơn giản.
markau

1
Bạn thậm chí có thể chuyển các cài đặt sang trường chỉ đọc tĩnh và thêm phương thức bổ sung FromJson.
Vapor trong hẻm

8

Đơn giản hơn là IMO!

Tại sao bạn không làm điều này?

public class CourseController : JsonController
{
    public ActionResult ManageCoursesModel()
    {
        return JsonContent(<somedata>);
    }
}

Bộ điều khiển lớp cơ sở đơn giản

public class JsonController : BaseController
{
    protected ContentResult JsonContent(Object data)
    {
        return new ContentResult
        {
            ContentType = "application/json",
             Content = JsonConvert.SerializeObject(data, new JsonSerializerSettings { 
              ContractResolver = new CamelCasePropertyNamesContractResolver() }),
            ContentEncoding = Encoding.UTF8
        };
    }
}

7

Trong ASP.NET Core MVC.

    public IActionResult Foo()
    {
        var data = GetData();

        var settings = new JsonSerializerSettings 
        { 
            ContractResolver = new CamelCasePropertyNamesContractResolver() 
        });

        return Json(data, settings);
    }

Và thậm chí tốt hơn, đặt nó trong tệp Startup.cs.
FatAlbert

6

Dưới đây là một phương thức hành động trả về một chuỗi json (cameCase) bằng cách tuần tự hóa một mảng các đối tượng.

public string GetSerializedCourseVms()
    {
        var courses = new[]
        {
            new CourseVm{Number = "CREA101", Name = "Care of Magical Creatures", Instructor ="Rubeus Hagrid"},
            new CourseVm{Number = "DARK502", Name = "Defence against dark arts", Instructor ="Severus Snape"},
            new CourseVm{Number = "TRAN201", Name = "Transfiguration", Instructor ="Minerva McGonal"}
        };
        var camelCaseFormatter = new JsonSerializerSettings();
        camelCaseFormatter.ContractResolver = new CamelCasePropertyNamesContractResolver();
        return JsonConvert.SerializeObject(courses, camelCaseFormatter);
    }

Lưu ý phiên bản JsonSerializerSinstall được truyền dưới dạng tham số thứ hai. Đó là những gì làm cho lạc đà xảy ra.


4

Tôi đã làm như thế này:

public static class JsonExtension
{
    public static string ToJson(this object value)
    {
        var settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            NullValueHandling = NullValueHandling.Ignore,
            ReferenceLoopHandling = ReferenceLoopHandling.Serialize
        };
        return JsonConvert.SerializeObject(value, settings);
    }
}

Đây là một phương thức mở rộng đơn giản trong lõi MVC, nó sẽ cung cấp khả năng ToJson () cho mọi đối tượng trong dự án của bạn, theo tôi trong một dự án MVC, hầu hết các đối tượng nên có khả năng trở thành json, tất nhiên nó phụ thuộc :)


Xem xét trích xuất biến "cài đặt" bên ngoài phương thức (như trường tĩnh riêng "camelCaseSinstall") để bạn không khởi tạo biến mới mỗi khi phương thức ToJson được gọi.
Ekus

4

Bạn phải đặt cài đặt trong tệp 'Startup.cs'

Bạn cũng phải xác định nó trong các giá trị mặc định của JsonConvert, đây là nếu sau này bạn muốn sử dụng trực tiếp thư viện để tuần tự hóa một đối tượng.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .AddJsonOptions(options => {
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
        JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
    }

Lưu ý rằng câu trả lời này là đúng cho ASP.NET Core, nhưng không phải là ASP.NET (là khung trong câu hỏi).
Nate Barbettini

0

Nếu bạn đang trả lại ActionResult trong api web lõi .net hoặc kết quả IHttpAction thì bạn có thể kết thúc mô hình của mình theo phương thức Ok () sẽ khớp với trường hợp trên giao diện người dùng của bạn và nối tiếp nó cho bạn. Không cần sử dụng JsonConvert. :)

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.