Erzwingen Sie Eigenschaftsnamen in Kleinbuchstaben von Json () in ASP.NET MVC

89

Angesichts der folgenden Klasse,

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

    public string Message { get; set; }
}

Ich gebe eines davon in einer Controller-Aktion wie folgt zurück:

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

Mein clientseitiges Framework erwartet jedoch, dass diese Eigenschaften Erfolg und Nachricht in Kleinbuchstaben sind. Ist dies eine Möglichkeit, diesen Gedanken beim normalen Json-Funktionsaufruf zu erreichen, ohne dass die Eigenschaftsnamen in Kleinbuchstaben angegeben werden müssen?

James Hughes
quelle

Antworten:

130

Um dies zu erreichen, implementieren Sie eine benutzerdefinierte VersionJsonResult wie hier: Erstellen eines benutzerdefinierten ValueType und Serialisieren mit einem benutzerdefinierten JsonResult (ursprünglicher Link tot) .

Verwenden Sie einen alternativen Serialisierer wie JSON.NET , der diese Art von Verhalten unterstützt, z.

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

Ergebnisse in

{
  "name": "Widget",
  "expiryDate": "\/Date(1292868060000)\/",
  "price": 9.99,
  "sizes": [
    "Small",
    "Medium",
    "Large"
  ]
}
James Hughes
quelle
1
Dieser Link funktioniert: james.newtonking.com/json/help/index.html?topic=html/…
Josef Engelfrost
Wenn Sie JSON.NET verwenden und nicht camelCase, sondern snake_case möchten, lesen Sie diese Übersicht, die mir wirklich geholfen hat! gist.github.com/crallen/9238178
Niclas Lindqvist
Wie deserialisiere ich? Ex. von "klein" bis "klein"
Turm
1
@NiclasLindqvist Für moderne JSON.NET-Versionen gibt es eine viel einfachere Möglichkeit, snake_case zu erhalten: newtonsoft.com/json/help/html/NamingStrategySnakeCase.htm
Søren Boisen
15

Das Ändern des Serializers ist einfach, wenn Sie die Web-API verwenden. Leider verwendet MVC selbst JavaScriptSerializerkeine Option, um dies für die Verwendung von JSON.Net zu ändern.

James 'Antwort und Daniels Antwort geben Ihnen die Flexibilität von JSON.Net, bedeuten jedoch, dass Sie überall dort, wo Sie normalerweise arbeiten würden return Json(obj), zu return new JsonNetResult(obj)oder ähnlich wechseln müssen, was sich bei einem großen Projekt als Problem erweisen könnte und auch nicht sehr flexibel ist, wenn Sie ändern Ihre Meinung zu dem Serializer, den Sie verwenden möchten.


Ich habe beschlossen, den ActionFilterWeg zu gehen . Mit dem folgenden Code können Sie eine beliebige Aktion JsonResultausführen und einfach ein Attribut anwenden, um JSON.Net (mit Eigenschaften in Kleinbuchstaben) zu verwenden:

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

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

Sie können dies sogar so einrichten, dass es automatisch auf alle Aktionen angewendet wird (mit nur dem geringfügigen Leistungseinbruch einer isPrüfung):

FilterConfig.cs

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

Der Code

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);
            }
        }
    }
}
dav_i
quelle
10

Mit meiner Lösung können Sie jede gewünschte Eigenschaft umbenennen.

Ich habe hier und auf SO einen Teil der Lösung gefunden

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

Damit ich das in meinem Controller tun kann

        return new JsonNetResult(result);

In meinem Modell kann ich jetzt haben:

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

Beachten Sie, dass Sie jetzt die JsonPropertyAttributefür jede Eigenschaft festlegen müssen, die Sie serialisieren möchten.

Daniel
quelle
1

Obwohl es eine alte Frage ist, wird die Hoffnung unter dem Code-Snippet für andere hilfreich sein.

Ich habe unten mit 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() });
    }
pgcan
quelle
0

Sie können diese Einstellung hinzufügen Global.asax, und sie funktioniert überall.

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;
         }; 
         //....
     }
}
Maksym Labutin
quelle