🙄

Strawberry Shake (.NET) で GraphQL #4 GraphQL の型とのマッピングのカスタマイズ

2024/12/10に公開

Strawberry Shake (.NET) で GraphQL #4 GraphQL の型とのマッピングのカスタマイズ

前回 GraphQL に Strawberry Shake を利用して Shopify の API を呼び出すことができましたが、うまくいかないケースもあったことを説明しました。今回はその対処方法その一です。

うまくいかなかったケース

次のように Shopify から商品の価格も含めて取得します。(Shopify に限らず、価格は商品だけでなく、サイズなどでも変化するため、商品の Variant が必要です)

GetProducts.graphql
query GetProducts {
    products(first: 100) {
        edges {
            node {
                id
                title
                variants(first: 100) {
                    edges {
                        node {
                            id
                            title
                            price {
                                amount
                            }
                        }
                    }
                }
            }
        }
    }
}

Rider での .graphql ファイルの実行は問題はないのですが、次のように .NET Decimal 型への変換に失敗します。

レスポンスを確認すると、該当のプロパティ (価格) がレスポンスの JSON は string 型でした。123.00 ではなく、"123.00" となっています。ここで変換ができなかったようです。

マッピングのカスタマイズ

GraphQL は型を自由に作ることができます。Shopify のスキーマを読むと、Decimal 型が宣言されています。Strawberry Shake はソースコードを自動生成しますので、Strawberry Shake 流の対処方法が必要になります。

まずは .NET String <-> .NET Decimal のコンバーターを書きます。

using StrawberryShake.Serialization;

namespace ConsoleApp1;

internal class String2DecimalSerializer() : ScalarSerializer<string, decimal>(BuiltInScalarNames.Decimal)
{
    public override decimal Parse(string serializedValue)
    {
        return decimal.Parse(serializedValue);
    }

    protected override string Format(decimal runtimeValue)
    {
        return runtimeValue.ToString();
    }
}

Program.cs のサービスの構成にこのコンバーターを追加します。

Program.cs
// ...

serviceCollection.AddSerializer<String2DecimalSerializer>();

var services = serviceCollection.BuildServiceProvider();

// ...

そして、schema.extensions.graphql ファイルに追加で GraphQL の Decimal 型をこのコンバーターを利用するようにします。次の内容を追記してください。

schema.exetensions.graphql
extend scalar Decimal
    @serializationType(name: "global::System.String")
    @runtimeType(name: "global::System.Decimal")

これでちゃんと動くようになりました。

詳しい方法やそれ以外のマッピングも含めて公式ドキュメントの Scalars に書いてあります。

最後に

Strawberry Shake は自動生成を伴うので、何か問題が起きたときの対処が StrawberryShake 流の解決方法を調べる必要があります。このあたりは自前でコードを書くスタイルのライブラリの方がやりやすいですよね。

次回はもう一つはまった GraphQL union の扱いです。

Discussion