2つのコントローラーコントローラーがあります:ControllerA
とControllerB
。各コントローラーの基本クラスはController
です。
ControllerA
は、デフォルトの形式(camelCase)でJSONを返す必要があります。 ControllerB
は、snake_caseという別のJSON形式でデータを返す必要があります。
これをASP.NET Core 3.xおよび2.1に実装するにはどうすればよいですか?
私はstartup
を試してみました:
services
.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new StringEnumConverter());
options.SerializerSettings.ContractResolver = new DefaultContractResolver()
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
})
.AddControllersAsServices();
ただし、これにより、ControllerB
だけでなく、allコントローラのシリアル化が変更されます。 1つのコントローラーに対してこの機能を構成または注釈を付けるにはどうすればよいですか?
Action Filter と Output Formatter の組み合わせでこれを実現できます。アクションフィルターの例を次に示します。
public class SnakeCaseAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext ctx)
{
if (ctx.Result is ObjectResult objectResult)
{
objectResult.Formatters.Add(new JsonOutputFormatter(
new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
},
ctx.HttpContext.RequestServices.GetRequiredService<ArrayPool<char>>()));
}
}
}
OnActionExecuted
を使用すると、コードは対応するアクションの後に実行され、最初に結果がObjectResult
(継承によりOkObjectResult
にも適用される)かどうかを確認します。 ObjectResult
の場合、フィルターはJsonOutputFormatter
を使用してプロパティをシリアル化する SnakeCaseNamingStrategy
のカスタマイズバージョンを追加するだけです。 JsonOutputFormatter
コンストラクターの2番目のパラメーターは、DIコンテナーから取得されます。
このフィルターを使用するには、関連するコントローラーに適用するだけです。
[SnakeCase]
public class ControllerB : Controller { }
3.0以降の場合、外観は少し異なります。3.0以降のデフォルトのJSONフォーマッターは、System.Text.Json
に基づいています。これを書いている時点では、これらは ヘビの場合の命名戦略に対する組み込みサポートはありません です。
ただし、Json.NETを3.0以降で使用している場合(詳細は docs にあります)、上記のSnakeCaseAttribute
はまだ実行可能ですが、いくつかの変更点があります。
JsonOutputFormatter
はNewtonsoftJsonOutputFormatter
になりました。NewtonsoftJsonOutputFormatter
コンストラクターには、MvcOptions
の引数が必要です。これがコードです:
public class SnakeCaseAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext ctx)
{
if (ctx.Result is ObjectResult objectResult)
{
objectResult.Formatters.Add(new NewtonsoftJsonOutputFormatter(
new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
},
ctx.HttpContext.RequestServices.GetRequiredService<ArrayPool<char>>(),
ctx.HttpContext.RequestServices.GetRequiredService<IOptions<MvcOptions>>().Value));
}
}
}
注:たとえば、JsonOutputFormatter
/NewtonsoftJsonOutputFormatter
をどこかで事前に作成することをお勧めします。これは、手元の質問の副次的なものなので、例ではそれほど進んでいません。
エンドポイントで使用するこのメソッドを作成することになりました:
{
// needed to get the same date and property formatting
// as the Search Service:
var settings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver()
{
NamingStrategy = new SnakeCaseNamingStrategy()
},
DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffZ"
};
return Json(result, settings);
}