Paksa nama properti huruf kecil dari Json () di ASP.NET MVC


89

Diberikan kelas berikut,

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

    public string Message { get; set; }
}

Saya mengembalikan salah satunya dalam tindakan Pengontrol seperti ini,

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

Namun kerangka sisi klien saya mengharapkan properti ini menjadi pesan dan kesuksesan huruf kecil. Tanpa benar-benar harus memiliki nama properti huruf kecil apakah itu cara untuk mencapai pemikiran ini panggilan fungsi Json normal?

Jawaban:


130

Cara untuk mencapainya adalah dengan menerapkan kustom JsonResultseperti di sini: Membuat ValueType dan Serialising kustom dengan JsonResult kustom (link asli mati) .

Dan gunakan serialiser alternatif seperti JSON.NET , yang mendukung perilaku semacam ini, misalnya:

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

Hasil dalam

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


Jika Anda menggunakan JSON.NET, dan tidak ingin camelCase tetapi snake_case, lihat inti ini, sangat membantu saya! gist.github.com/crallen/9238178
Niclas Lindqvist

Bagaimana cara menghilangkan derialisasi? Ex. dari "kecil" menjadi "Kecil"
benteng

1
@NiclasLindqvist Untuk versi JSON.NET modern, ada cara yang jauh lebih sederhana untuk mendapatkan snake_case: newtonsoft.com/json/help/html/NamingStrategySnakeCase.htm
Søren Boisen

17

Mengubah serializer itu sederhana jika Anda menggunakan API Web, tetapi sayangnya MVC sendiri menggunakan JavaScriptSerializertanpa opsi untuk mengubahnya untuk menggunakan JSON.Net.

Jawaban James dan jawaban Daniel memberi Anda fleksibilitas JSON.Net tetapi berarti bahwa di mana pun Anda biasanya berada, return Json(obj)Anda harus mengubah return new JsonNetResult(obj)atau serupa yang jika Anda memiliki proyek besar dapat membuktikan masalah, dan juga tidak terlalu fleksibel jika Anda berubah pikiran pada serializer yang ingin Anda gunakan.


Saya telah memutuskan untuk mengikuti ActionFilterrute tersebut. Kode di bawah ini memungkinkan Anda untuk mengambil tindakan apa pun menggunakan JsonResultdan cukup menerapkan atribut padanya untuk menggunakan JSON.Net (dengan properti huruf kecil):

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

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

Anda bahkan dapat mengatur ini agar secara otomatis diterapkan ke semua tindakan (dengan hanya kinerja kecil dari sebuah iscek):

FilterConfig.cs

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

Kode

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

Dengan solusi saya, Anda dapat mengganti nama setiap properti yang Anda inginkan.

Saya telah menemukan bagian dari solusi di sini dan di 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();
        }
    }

Sehingga di pengontrol saya, saya bisa melakukan itu

        return new JsonNetResult(result);

Dalam model saya, sekarang saya dapat memiliki:

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

Perhatikan bahwa sekarang, Anda harus menyetel JsonPropertyAttributeke setiap properti yang ingin Anda buat serialnya.


1

Meskipun ini adalah pertanyaan lama, semoga cuplikan kode di bawah ini akan membantu orang lain,

Saya lakukan di bawah ini dengan 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() });
    }

0

Anda dapat menambahkan pengaturan ini ke Global.asax, dan ini akan berfungsi di mana saja.

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;
         }; 
         //....
     }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.