Bagaimana saya bisa mengembalikan camelCase JSON berseri oleh JSON.NET dari metode pengontrol ASP.NET MVC?

246

Masalah saya adalah bahwa saya ingin mengembalikan data JSON camelCased (sebagai lawan dari PascalCase standar) melalui ActionResult dari metode pengontrol ASP.NET MVC, yang diserialkan oleh JSON.NET .

Sebagai contoh, pertimbangkan kelas C # berikut:

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

Secara default, saat mengembalikan instance kelas ini dari pengontrol MVC sebagai JSON, itu akan diserialisasi dengan cara berikut:

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

Saya ingin serialisasi (oleh JSON.NET) sebagai:

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

Bagaimana saya melakukan ini?

aknuds1
sumber

Jawaban:

389

atau, cukup cantumkan:

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

Misalnya:

return new ContentResult
{
    ContentType = "application/json",
    Content = JsonConvert.SerializeObject(new { content = result, rows = dto }, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }),
    ContentEncoding = Encoding.UTF8
};
WebDever
sumber
2
Ini lebih kompleks untuk digunakan, karena Anda harus mengonfigurasi ContentResult untuk setiap metode pengontrol.
aknuds1
2
Ya saya mengerti bahwa jawaban Anda adalah solusi yang dapat digunakan kembali, maksud saya adalah untuk membuatnya lebih jelas bahwa itu hanya parameter pada metode Serialize.
WebDever
1
Jika Anda mengembalikan JSON dari suatu Controllermetode, Anda mungkin harus menggunakan ApiController, dalam hal ini jawaban ini berfungsi dengan baik.
Simon Hartcher
1
@SimonHartcher Pertimbangkan ruang lingkup pertanyaan, bukan kasus umum.
aknuds1
1
Tipe konten yang valid untuk JSON adalah application/json, tidak text/plain.
Fred
94

Saya menemukan solusi yang sangat baik untuk masalah ini di blog Mats Karlsson . Solusinya adalah menulis subkelas ActionResult yang membuat serialisasi data melalui JSON.NET, mengonfigurasi yang terakhir untuk mengikuti konvensi 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));
    }
}

Kemudian gunakan kelas ini sebagai berikut dalam metode pengontrol MVC Anda:

public ActionResult GetPerson()
{
    return new JsonCamelCaseResult(new Person { FirstName = "Joe", LastName = "Public" }, JsonRequestBehavior.AllowGet)};
}
aknuds1
sumber
3
Jawaban sempurna: bersih dan dapat digunakan kembali! Terima kasih.
sander
1
Sementara solusi ini masih berfungsi. tetapi disarankan 4 tahun yang lalu. Apakah kita punya solusi yang lebih baik?
SharpCoder
59

Untuk WebAPI , lihat tautan ini: http://odetocode.com/blogs/scott/archive/2013/03/25/asp-net-webapi-tip-3-camelcasing-json.aspx

Pada dasarnya, tambahkan kode ini ke Application_Start:

var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
Assaf S.
sumber
4
API Web dan MVC telah digabung dalam ASP.NET 6
AlexFoxGill
1
Menautkan untuk kenyamanan; setup ini sangat cocok dengan jawaban ini: stackoverflow.com/a/26068063/398630 (pertanyaan berbeda, tapi saya menggunakannya bersama-sama, dan tautan ini mungkin menyelamatkan saya dan orang lain beberapa googling di masa depan).
BrainSlugs83
37

Saya pikir ini adalah jawaban sederhana yang Anda cari. Ini dari blog Shawn Wildermuth :

// Add MVC services to the services container.
services.AddMvc()
  .AddJsonOptions(opts =>
  {
    opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
  });
Kuantium
sumber
2
Permintaan maaf saya, teman-teman Saya membaca posting ini terlalu cepat. Ini untuk ASP.NET 5.
Quantium
8
Ironisnya, saya datang ke sini mencari jawaban untuk pertanyaan yang Anda jawab di sini, jadi meskipun itu bukan jawaban untuk pertanyaan OP, itu tetap membantu saya. Terima kasih! :)
porcus
1
Saya kedua apa yang @porcus katakan! Terima kasih @ Kuantium!
Gromer
4
fyi Untuk ASP.NET Core 1.0, ini unta kasus secara default OOTB
Chris Marisic
3
Ternyata ini bukan (tepatnya) default untuk .NET Core 1.0 setelah semua. Solusi ini memengaruhi properti dinamis dan tidak terpengaruh secara default. stackoverflow.com/questions/41329279/…
Niels Brinch
13

Alternatif untuk filter khusus adalah membuat metode ekstensi untuk membuat serialisasi objek apa pun ke 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);
    }
}

Kemudian panggil ketika kembali dari aksi controller.

return Content(person.ToJson(), "application/json");
Stuart Hallows
sumber
Elegan dan sederhana.
markau
1
Anda bahkan dapat mentransfer pengaturan ke bidang baca statis dan menambahkan metode komplemen FromJson.
Menguap di Gang
8

Lebih sederhana adalah IMO yang lebih baik!

Kenapa kamu tidak melakukan ini?

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

Pengontrol kelas dasar sederhana

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
        };
    }
}
jwize
sumber
7

Dalam ASP.NET Core MVC.

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

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

        return Json(data, settings);
    }
Fred
sumber
Dan lebih baik lagi, letakkan di file Startup.cs.
FatAlbert
6

Di bawah ini adalah metode tindakan yang mengembalikan string json (cameCase) dengan membuat serial suatu array objek.

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

Perhatikan instance JsonSerializerSettings dilewatkan sebagai parameter kedua. Itulah yang membuat camelCase terjadi.

DanKodi
sumber
4

Saya memang suka ini:

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

ini metode ekstensi sederhana dalam inti MVC, itu akan memberikan kemampuan ToJson () untuk setiap objek dalam proyek Anda, Menurut pendapat saya dalam proyek MVC sebagian besar objek harus memiliki kemampuan untuk menjadi json, tentu saja itu tergantung :)

Ali Alp
sumber
Pertimbangkan mengekstraksi variabel "pengaturan" di luar metode (sebagai bidang statis pribadi "camelCaseSettings") sehingga Anda tidak menginisialisasi variabel baru setiap kali metode ToJson dipanggil.
Ekus
4

Anda harus mengatur pengaturan di file 'Startup.cs'

Anda juga harus mendefinisikannya dalam nilai-nilai default JsonConvert, ini adalah jika nanti Anda ingin langsung menggunakan perpustakaan untuk membuat serialisasi objek.

    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()
        };
    }
Daniel Sánchez
sumber
Perhatikan bahwa jawaban ini benar untuk ASP.NET Core, tetapi tidak untuk ASP.NET (yang merupakan kerangka kerja dalam pertanyaan).
Nate Barbettini
0

Jika Anda mengembalikan ActionResult di .net core web api, atau hasil IHttpAction maka Anda cukup membungkus model Anda dalam metode Ok () yang akan cocok dengan kasing di ujung depan dan membuat serial untuk Anda. Tidak perlu menggunakan JsonConvert. :)

Luke Perrin
sumber