web-dev-qa-db-ja.com

Azure Functions 3.0の属性を使用してEnumを文字列としてシリアル化する

Azure Functions 3.0/3.1アプリでHTTPトリガーを取得して、運のない列挙型の文字列表現を返すことを試みました。 Core 3.0とCore 3.1の両方を試しました。

このクラスを考えると:

_public enum TestEnum
{
   TestValue
}

public class TestClass
{ 
   public TestEnum Test { get; set; }
}
_

私はこのHTTPトリガーを期待します:

_[FunctionName("MyHttpTrigger")]
public static IActionResult Run(
   [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
    return new OkObjectResult(new TestClass { Test = TestEnum.TestValue });
}
_

_{ "test": "TestValue" }_を返します。代わりに、_{ "test": 0 }_を返します。

.Net Core 2では、名前空間_Newtonsoft.Json_から[JsonConverter(typeof(StringEnumConverter))]を使用して列挙型を装飾し、これを実現できました。これは現在機能しません。

.Net Core 3が_System.Text.Json_- namespaceでコンバーターに切り替えたことを知っているので、名前空間_System.Text.Json.Serialization_から[JsonConverter(typeof(JsonStringEnumConverter))]で同じ列挙型を修飾してみました。これも機能しませんでした。

他のすべての同様の問題は、上記が機能するか、または this のように、.AddControllers()または.AddMvc()でJsonOptionsを構成して解決することを示しています-chain、ただし機能しない機能アプリの場合。関数ランタイムはコントローラーのセットアップを担当するため、追加の構成AFAIKに直接アクセスすることはできません。

この問題は、コアツールを使用した最小限のAzure Functionsプロジェクトで再現可能です。

_func init MyFunctionProj
cd MyFunctionProj
func new --name MyHttpTrigger --template "HttpTrigger"
_

次に、httpトリガーを変更して、内部に列挙型を持つオブジェクトを返します。

私のバージョン:

_> func --version
3.0.1975
> dotnet --version
3.1.100
_

追加情報

私は複数の回避策を試しましたので、ここに私の観察の一部を示します。 OkObjectResultObjectResultExecutor によって処理されます。実装を自分のソリューションにコピーし、DIコンテナーに追加してデバッグできるようにしました:

_builder.Services.AddSingleton<IActionResultExecutor<ObjectResult>, TestExecutor>();

_

リンクされたソースの101行目で、フォーマッタが選択されています。興味深いことに、この時点で中断すると、選択されたフォーマッターは NewtonsoftJsonOutputFormatter !になります。最初のJsonConverter- attributeはこれで動作するはずですが、動作しません。

使用可能な出力フォーマッターのリストを変更するのは一見の価値があると思いました。 ActionResultExecutorは DefaultOutputFormatterSelector を使用して選択を行い、次に_IOptions<MvcOptions>_を挿入して出力フォーマッターを取得します。

DefaultOutputFormatterSelectorに異なる選択を強制するために、私はこれを試しました:

_class MvcOptionsConfiguration : IPostConfigureOptions<MvcOptions> 
{
...
}

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.ConfigureOptions<MvcOptionsConfiguration>();
    }
}
_

通常の_IConfigureOptions<T>_は、_options.Outputformatters_- collectionには_Microsoft.AspNetCore.Mvc.WebApiCompatShim.HttpResponseMessageOutputFormatter_以外のすべてのフォーマッターが欠落していたため、使用できなかったことに注意してください。これは、それ自体が奇妙です(なぜ、互換性シム?).

タイプNewtonsoftJsonOutputFormatterをコレクションから削除しようとしました:

_options.OutputFormatters.RemoveType<NewtonsoftJsonOutputFormatter>();
_

そのためには、nugetパッケージ_Microsoft.AspNetCore.Mvc.NewtonsoftJson_を参照して型にアクセスする必要がありましたが、参照したときの型は、ランタイムで使用される型とは異なりました。ランタイムで使用される型の_type.Assembly.CodeBase_は_%USERPROFILE%/AppData/Local/AzureFunctionsTools/_にありましたが、nugetからの型は_Project root/bin/Debug_にありました。私はこれにこれまで遭遇したことがありません。通常、パッケージは一時的な依存関係になるため、自分で明示的にパッケージに依存せずに参照できるため、ここで何が行われているのか本当にわかりません。これは正常ですか、それとも私の環境に問題がありますか?

別の方法でそれを削除したとき、それは問題ではなく、とにかく選択されたので、MvcOptionsに注入されたDefaultOutputFormatterSelectorは同じではないようですMvcOptionsスタートアップで。

この時点で、私はリードを使い果たして、あなたたちに向けました。私を正しい方向に向けてくれる人がいるといいのですが。

6
CHochlin

私は次のコードを使用してこれを機能させることができました

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Converters;

[Assembly: FunctionsStartup(typeof(Configs.Startup))]

namespace Configs
{
    class Startup : FunctionsStartup
    {
       public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddMvcCore().AddNewtonsoftJson(x =>
            {
                x.SerializerSettings.Converters.Add(new StringEnumConverter());
            });
        }
    }
}

これは、Azure Functions Core Tools(3.0.2534 Commit hash:bc1e9efa8fa78dd1a138dd1ac1ebef97aac8d78e)のnetcoreapp3.1および次のパッケージを含むFunction Runtime Version:3.0.13353.0にありました。

<PackageReference Include="AsyncEnumerator" Version="4.0.2" />
<PackageReference Include="AzureFunctions.Autofac" Version="4.0.0" />
<PackageReference Include="CsvHelper" Version="15.0.5" />
<PackageReference Include="Dapper" Version="2.0.35" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.4" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />

うまくいけば、これは誰かを助けます。

ここにサンプルのリポジトリをプッシュしました: https://github.com/rawrspace/string-enum-example

編集:今日も同じ設定でこれを使用しており、[JsonConverter(typeof(StringEnumConverter))]を使用すると完全に問題なく動作しました。最近更新が行われたかどうかはわかりませんが、念のため上記のソリューションは残しておきます。

1