NancyFxでWebAPIを作るときに必ず参照すべきライブラリ

1年以上ぶりにNancyFxネタ。日本語の情報があまりないので、色々書いて行こうと思います。
ユーザが増えてくれれば嬉しいですね。

さてNancyFxでは、デフォルトでJsonレスポンスを返すことが出来ます。

Get["/json"] = _ => {
    var data = new {
        Id = 1,
        Name = "rabitarochan",
        BlogUrl = "http://rabitarochan.hatenablog.com/"
    };

    return Response.AsJson(data);
};

ブラウザからこのURLにアクセスすると、以下のようなJsonが返ります。

{
    Id: 1,
    Name: "rabitarochan",
    BlogUrl: "http://rabitarochan.hatenablog.com/"
}

よくよく見てみると、キーがC#のプロパティ名と同じUpperCamelCaseとなっていますね。
そのため、JavaScript側でも同じくUpperCamelCaseで扱う必要があります。

ただし、JavaScriptではほとんどの場合、lowerCamelCaseが使われていると思いますので、JavaScript側がちょっと気持ち悪い感じになってしまいます。

できればNancyFxからJsonを返す際に、キーをlowerCamelCaseに変換してくれればベストです。
NancyFxのソースを読んでみましたが、残念ながらキーとなる文字列を変換するオプション等はありませんでした。

(ちなみに、NancyFxは独自のJsonシリアライザを使っています。)

そこでNancy.Serialization.JsonNetの出番です!

リポジトリはこちら。NuGetからもインストール可能です。

https://github.com/NancyFx/Nancy.Serialization.JsonNet

このライブラリは、Jsonレスポンスを返す際のシリアライザとして、C#からJsonを扱う際に一番使われていると思われるライブラリJson.Netを使うように変更してくれるだけのものです。

そして、Json.NetJsonSerializerクラスを少し変更するだけで、キーをlowerCamelCaseに変換することが可能です!!

設定方法

設定はとても簡単で、シリアライザを継承したクラスを1つ作成することと、それをDIコンテナに登録することだけです。

リアライザを継承したクラスを作成する

Json.Net用のシリアライザを継承したクラスを作成します。今回と同じ目的の場合は、以下のコードをコピペでOKです。
詳細については、Json.Netのドキュメントを参照してください。

public class CustomJsonSerializer : JsonSerializer
{
    public CustomJsonSerializer()
    {
        this.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}

DIコンテナに登録する

Bootstrapperクラスにて、DIコンテナTinyIocに先ほど作成したクラスを登録します。

public class Bootstrapper : DefaultNancyBootstrapper
{
    protected override void ConfigureApplicationContainer(Nancy.TinyIoc.TinyIoCContainer container)
    {
        base.ConfigureApplicationContainer(container);

        container.Register(typeof(JsonSerializer), typeof(CustomJsonSerializer));
    }
}

仕組み

Nancy.Serialization.JsonNetは、JsonのシリアライザとしてJson.Netを利用するように変更してくれるプラグインのようなものです。

NancyFxでは、コンテントタイプ毎に任意のシリアライザが登録できる仕組みになっているようです。
(その仕組みまではまだ見ていません。)

デフォルトではJson.NetJsonSerializerをそのまま使用しますが、BootStrapperクラスにて今回作成したようなクラスを登録してあげることで、そちらのクラスが使用される、ということです。

最初に書いたソースはそのままで同じURLにアクセスすると、ちゃんとlowerCamelCaseに変換されていることが分かります。

{
    id: 1,
    name: "rabitarochan",
    blogUrl: "http://rabitarochan.hatenablog.com/"
}

シリアライズは??

PostされたJsonをC#のクラスに変換する場合は、UpperCamelCaselowerCamelCase関係なく変換してくれます。

変換には、NancyFxが提供しているModelBindingという仕組みを利用します。

以下の例では、フォームからPostされたパラメータをクラスに変換し、そのままJsonレスポンスとして返しています。

namespace NancyJsonTest.Modules
{
    using Nancy;
    using Nancy.ModelBinding; // クラスに変換するための拡張メソッド用。

    public class HomeModule : NancyModule
    {
        // フォーム値用のクラス
        class TestForm
        {
            // input type=text name=userName
            public string UserName { get; set; }
            
            // input type=password name=password
            public string Password { get; set; }
        }
        
        public HomeModule()
        {
            Get["/json"] = _ => {
                var data = new {
                    Id = 1,
                    Name = "rabitarochan",
                    BlogUrl = "http://rabitarochan.hatenablog.com/"
                };

                return Response.AsJson(data);
            };

            Post["/json"] = _ => {
                var form = this.Bind<TestForm>();

                return Response.AsJson(form);
            };        
        }
    }
}

まとめ

このライブラリを利用することで、C#JavaScriptのプロパティ名の違いがほぼ吸収できると思います。

NancyFxでWebAPIを作成するときは、ぜひこのライブラリを利用してみてください。