web-dev-qa-db-ja.com

MVC 4での適切なJSONシリアル化

JSONを「適切に」シリアル化(camelCase)し、必要に応じて日付形式を変更できるようにします。

Web APIの場合、非常に簡単です-Global.asaxで次のコードを実行します

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

このコードは、パイプラインレベルで、好きな方法でシリアル化を処理します。

MVC 4でも同じことを実現したいと考えています。コントローラーアクションメソッドから返されたJSONが適切にシリアル化されるようにします。少し調べてみると、Global.asaxアプリケーションの起動時にスローする次のコードが見つかりました。

HttpConfiguration config = GlobalConfiguration.Configuration;
Int32 index = config.Formatters.IndexOf(config.Formatters.JsonFormatter);
config.Formatters[index] = new JsonMediaTypeFormatter
{
     SerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }
};

正常に実行されるようですが、コントローラーからJSONを返すと、すべてPascalCasedです。私のアクションメソッドの簡単な例:

private JsonResult GetJsonTest()
{
    var returnData = dataLayer.GetSomeObject();
    return Json(returnData, JsonRequestBehavior.AllowGet);
}

私はこれについて間違っていますか?パイプラインレベルでこれを達成する方法はありますか?

43
Mario

MVCアプリケーションでJson出力を処理するには、ServiceStackやJson.NETなどを使用することをお勧めします。ただし、クラスを簡単に記述し、基本クラスを使用してJsonメソッドをオーバーライドできます。以下の例を参照してください。

注:これにより、Global.ascx.csファイルには何も必要ありません。

カスタムJsonDotNetResultクラス:

public class JsonDotNetResult : JsonResult
{
    private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver(),
        Converters = new List<JsonConverter> { new StringEnumConverter() }
    };

    public override void ExecuteResult(ControllerContext context)
    {
        if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
            string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("GET request not allowed");
        }

        var response = context.HttpContext.Response;

        response.ContentType = !string.IsNullOrEmpty(this.ContentType) ? this.ContentType : "application/json";

        if (this.ContentEncoding != null)
        {
            response.ContentEncoding = this.ContentEncoding;
        }

        if (this.Data == null)
        {
            return;
        }

        response.Write(JsonConvert.SerializeObject(this.Data, Settings));
    }
}

ベースコントローラークラス:

public abstract class Controller : System.Web.Mvc.Controller
{
    protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new JsonDotNetResult
            {
                Data = data,
                ContentType = contentType,
                ContentEncoding = contentEncoding,
                JsonRequestBehavior = behavior
            };
    }
}

これで、コントローラーアクションで、そのようなものを返すことができます。

return Json(myObject, JsonRequestBehavior.AllowGet);

バム。 Jsonで返されるキャメルケースオブジェクトがあります:)

注:Jsonで作成する各オブジェクトのシリアライザー設定でこれを行う方法があります。しかし、Jsonを返したいと思うたびに、誰がそれをタイプしたいでしょうか?

88
technicallyjosh

Web APIはJSON.NETを使用しますが、MVC4はデフォルトでJavaScriptSerializerを使用しますが、キャメルケースシリアル化への変更をサポートするとは思いません。これを確認してください: ASP.NET MVCでデフォルトのJSONシリアライザーを設定する

私の提案は、ここで説明されているようにカスタムJsonNetResultを作成することです ASP.NET MVC 3でデフォルトのJSONシリアライザーとしてJSON.NETを使用する-可能ですか? に変更し、最後の行を次のように変更します:

var serializedObject = JsonConvert.SerializeObject(
      Data,
      Formatting.Indented, ,
      new JsonSerializerSettings { MappingResolver = new CamelCaseMappingResolver() });
6
fcuesta
Note that below information is for Asp .Net core

.Netチームは最近、MVCがデフォルトでキャメルケース名でJSONをシリアル化することを発表しました。

以下の数行を使用すると、この機能を有効にできます。

services
.AddMvc()
.AddJsonOptions(options =>
options.SerializerSettings.ContractResolver = new DefaultContractResolver());

here である同じものに関する小さなブログを書きました。

5
Neel