ASP.NET MVC'de Json () 'dan küçük harf özellik adlarını zorla


90

Aşağıdaki sınıf göz önüne alındığında,

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

    public string Message { get; set; }
}

Bunlardan birini şu şekilde bir Denetleyici eyleminde iade ediyorum,

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

Ancak, istemci tarafı çerçevem ​​bu özelliklerin küçük harf başarı ve mesaj olmasını bekliyor. Aslında küçük harf özellik adlarına sahip olmak zorunda kalmadan, bu düşünceyi elde etmenin bir yolu normal Json işlev çağrısı mı?

Yanıtlar:


132

Bunu başarmanın yolu, aşağıdaki JsonResultgibi bir özel uygulamaktır : Özel bir ValueType oluşturma ve özel bir JsonResult ile Seri Oluşturma (orijinal bağlantı ölü) .

Ve bu tür davranışları destekleyen JSON.NET gibi alternatif bir serileştirici kullanın , örneğin:

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

Sonuçlar

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


JSON.NET kullanıyorsanız ve camelCase değil snake_case istiyorsanız, bu özü inceleyin, bana gerçekten yardımcı oldu! gist.github.com/crallen/9238178
Niclas Lindqvist

Seri durumdan nasıl çıkarırım? Örn. "küçük" ten "Küçük" e
kale

1
@NiclasLindqvist Modern JSON.NET sürümleri için, snake_case'i edinmenin çok daha basit bir yolu var: newtonsoft.com/json/help/html/NamingStrategySnakeCase.htm
Søren Boisen

17

Web API kullanıyorsanız serileştiriciyi değiştirmek basittir, ancak maalesef MVC JavaScriptSerializerbunu JSON.Net kullanmak için değiştirme seçeneği olmadan kullanır .

James'in cevabı ve Daniel'in cevabı size JSON.Net'in esnekliğini verir, ancak normalde yapacağınız her yerde , büyük bir projeniz varsa bir problemi ispatlayabilecek veya benzerine return Json(obj)geçmeniz gerektiği anlamına gelir return new JsonNetResult(obj)ve eğer kullanmak istediğiniz serileştiricide fikrinizi değiştirirsiniz.


Rotadan aşağı inmeye karar verdim ActionFilter. Aşağıdaki kod kullanarak herhangi bir işlem yapmanıza JsonResultve JSON.Net'i (küçük harf özellikleriyle) kullanmak için ona bir öznitelik uygulamanıza olanak tanır :

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

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

Hatta bunu tüm eylemlere otomatik olarak uygulanacak şekilde ayarlayabilirsiniz (bir çekte yalnızca küçük performans isabeti ile is):

FilterConfig.cs

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

Kod

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

Benim çözümümle istediğiniz her mülkü yeniden adlandırabilirsiniz.

Çözümün bir kısmını burada ve SO'da buldum

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

Böylece kontrol cihazımda bunu yapabilirim

        return new JsonNetResult(result);

Modelimde artık şunlara sahip olabilirim:

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

Şimdi, JsonPropertyAttributeserileştirmek istediğiniz her özelliğe ayarlamanız gerektiğini unutmayın.


1

Bu eski bir soru olsa da, aşağıdaki kod pasajının başkalarına yardımcı olacağını umuyoruz.

Aşağıda MVC5 Web API ile yaptım.

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

Bu ayarı öğesine ekleyebilirsiniz Global.asaxve her yerde çalışacaktır.

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;
         }; 
         //....
     }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.