まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

emoji(絵文字)はもともと(当時の) NTT ドコモのエンジニアであった栗田穣崇さんが 1990 年代にiモードの立ち上げ時のコミュニケーション手段の1つとして開発されました。当時は 12x12 ピクセルの中で記号やピクトグラムが表現されていました:
d_202110_001


この「コミュニケーション手段としての emoji」や「感情を効果的に伝える emoji」は 2000 年以降になって日本だけでなく世界中に広がり、iPhone や Android の入力モードにも採用され、広く使われるようになりました。現在は Unicode コンソーシアムによって Unicode(ユニコード)の一部としても管理されています(以下 "Unicode Emoji" と表記します)。2022年11月の時点では Ver.15 の文字セットが登録されています。この Ver.15 で新しくリリースされた文字はここから参照することができます:
https://www.unicode.org/emoji/charts/emoji-released.html


そして、この Unicode Emoji はコンソーシアムによる提案・採用だけでなく、現在規定されていない文字を誰でも提案することができます。世界中で新たな文字として使われるべき理由・背景などを具体的なサンプル画像と合わせて規定のフォーマットで申請することができます。もちろん申請=即採用!とはならず、審査を経た上で主張に同意された場合のみ新しい Unicode Emoji として採用されることになります。

この Unicode Emoji の申請方法は原則英語で記述する必要があり、また1年ごとの申請となるので次回(2023年)申請時のルールは現在わかっているもの(2022年)とは変わる可能性もあります。が、大まかには変わらないだろう、という希望的観測の元で、申請方法を日本語でまとめ直してみました。


【理解しておくべき大原則】
まず(私も最初は誤解していたのですが)理解しておくべき大原則として、「採用=申請した画像が採用される」ではないという点を理解しておく必要があります。申請時にサンプルとして画像ファイルを添付する必要はありますが、その画像がそのまま Unicode Emoji として採用されるわけではない、ということです。あくまで Unicode Emoji の登録文字としての採用であって、例えば iPhone や Android の入力時にどのように表示されるかや、Twitter で表示される時にどのような文字グラフィックで表示されるか、はあくまでスポンサー企業である Apple, Google, Twitter 社が決めることです。ただその際の参考画像にはなると思っています。

次に Unicode Emoji は世界中で使われる可能性がある点を理解した上で申請する必要がある、という点です。日本独自の(世界的にはマイナーな)文化であったり、世界中で知られている文化であった場合でもそのサンプル画像が日本独自なもの(日本以外では見た目が異なる場合)だと、その Unicode Emoji 画像を見ても日本以外では意味が通じなくなってしまう可能性がある、という点です。

これらを誤解して内輪ネタを提案しても(決めるのはあくまで Unicode コンソーシアムですが)採用される可能性は高くないし、採用されても提案されたイメージとは違う画像になる可能性もある、ということは理解した上で申請すべきことを最初に書いておきます。

以下に記載する内容は 2022 年11月時点で、ここに記載されているものをベースに日本語で書き直したものです。最新の条件は変わっている可能性があるので、申請する場合は忘れずに一次情報を確認するようにしてください:
https://unicode.org/emoji/proposals.html


【申請タイミング】
Unicode Emoji の申請は年中募集中というわけではありません。毎年 4/1 から 7/31 まで受け付けており、2022 年の募集は終わっています。今から申請する場合は 2023 年募集分として 2023/04/01 から受け付けることになる、という点に注意してください(とはいえ準備する項目が多いので、早い段階から準備を進めておくことは悪い事ではないと思っています)。


【申請前に調べておくこと】
Unicode Emoji を申請する上では、既にその Unicode Emoji が採用されていたり、過去に同様の申請がされていたりしないことを確認しておくべきです。採用されているかどうかは実際にスマホで探してみることもできますが、過去に申請されているかどうかは調べてみないとわかりません。

過去に(Unicode コンソーシアムからではなく)一般から応募のあった Unicode Emoji はこちらから調べることができます:
https://www.unicode.org/emoji/emoji-requests.html

(英語の壁はありますが)ここから過去に申請された Emoji と、その結果が色分けされて表示されています。少なくともこれから申請しようとしている Emoji が既に登録済みではなく、過去に申請されてもいないことは確認しておきましょう。


【申請時の判断基準】
Unicode Emoji として提案したい文字画像を1つ用意すればよい、という簡単なものではありません。むしろ心が折れそうになるくらい面倒で膨大な準備が必要です。

ただ申請内容をどのように判断するか、その基準は公開されています:
https://www.unicode.org/emoji/proposals.html#selection_factors

↑ここに書かれた内容を1つずつ確認しつつ、何を準備する必要があるのかを確認してみます。以下、英語で書かれている内容を日本語化して紹介します:

(プラス要素(ポジティブに評価される要素))
A. 互換性

Twitter などのシステムでは用意されているアイコンで、まだ Unicode Emoji としては登録されていないものか?

B. 使用レベル

世の中でどのくらい頻繁に使われているものか?キーワードで検索した結果であったり、既存の絵文字の組み合わせでも表現できないものであったり、同じアイコンが違う意図でも使えたりする要素があるか?

C. 独自性

絵文字は明確であるか?視覚的にも象徴的であるか(他と間違えにくいか)?

D. 完全性

似たようなものが既に登録されていないか? 狭いカテゴリー内での異なる種別であったりしないか?


(マイナス要素(ネガティブに評価される要素))
E. 過度に頻繁な申請

「ツイッターで話題」とか「嘆願書」は客観性を欠くと判断される。

F. 過度に具体的

ある大きなグループの中の特定種別だけが切り出されて申請されていないか?

G. オープンエンドであるもの

大きなグループ内の他のものと比較して、その1つを選ぶ理由がないもの

H. 他の Unicode Emoji の組み合わせで実現できそうなもの

例:「ジャックオランタン」+「ゴースト」=「ハロウィン」

I. 著作権に関わるもの

ロゴ、ブランド、知的財産権のある画像、架空の人物、歴史上の人物、特定の建物、神々、・・など

J. 人気が一時的なもの

一時的に使用レベルは上がる可能性はあるが、今後も続く可能性が低いと判断されるもの

K. 誤った比較

「これとは似ていない」という主張が間違っていると判断されるもの

L. 正確な画像が要求されるもの

どのような画像が用意されるかはスポンサー企業が決めるものです

M. 地域フラグのないもの

特定の地域だけで使われるものではなく、世界中で同じ意味で使われるもの

N. 権利やライセンスが欠如しているもの

例えば画像に利用ライセンスが必要な場合は、そのための書類も必要

O. 方向のバリエーションがあるもの

例えば「(右に向かって走る)ランナー」が存在している場合の、「左に走るランナー」のようなものは認めない(といいつつ、上のリンク先でもある Ver.15 ではこれに該当するような新採用文字も含まれているような・・・)

P. 画像内にテキストを含むもの

国際的に認識できない可能性があるため


【申請時に必要なもの】
以上の要件を頭に入れた上で、実際の申請時に必要そうなものを書きだしてみます。

・同意書
https://www.unicode.org/emoji/emoji-proposal-agreement.pdf

申請時に使う画像が自分のもの、あるいはパブリックドメインであることに同意する書類です。ダウンロードして署名する必要があります。


・申請フォーム
2022 年版の申請フォームが有志によって公開されています:
https://docs.google.com/document/d/1cTHKDI_AQrEdp3YHjeyP3L3RZxU_S0rfMZ16BJYmrGo/edit#

(2023 年申請のルールがどれほど変わるかわかりませんが)とりあえずこのフォームをダウンロードして、上述の情報となる画像やスクリーンショットを含めたり、書き埋めていくのが基本的な流れになります。

最終的には PDF で提出する必要があるため、PDF 化します。


・画像ファイル

用意するアイコン画像は以下の4つです:
・18x18 モノクロ
・18x18 カラー
・72x72 モノクロ
・72x72 カラー

72x72 がスマホ向け、18x18 がフィーチャーフォン(ガラケー)向けのようです。

なお「モノクロ」とは白と黒の2色だけからなるものです。「グレースケール(灰色も含む)」ではありません


これら申請に必要なファイルを1つの zip ファイルにまとめます。


【申請先】
2023 年の応募が始まってから、こちらからアップロードできるようになるようです(現在は受け付けしていません):
https://forms.gle/VYh55rc3seGjGNtEA



(↑新しい情報が分かり次第に上の情報を更新したり、追加したりするつもりです)


来年(2023年)、自分も1つ申請に挑戦するつもりです。上の情報だけでは足りなかったり、よく分からない点が出てきたりするかもしれませんが、興味ある方同志で協力しあって進めていければ、と考えています。






 

マーメイド記法を勉強している中で生じたアイデアを実装したら、なんとなくノーコード/ローコードっぽい仕上がりになり、自分で使っていても便利に感じたので公開して紹介することにしました。


【マーメイド記法とは】
最初に「マーメイド記法」について紹介します。マーメイド記法とは「特定のルールでテキストを記述することでフローチャート図を作る」ための記述ルールです。マークダウン記法の一種ですが、実際にマークダウンの中に含める形で使うこともできるようなサービスもあります。有名どころでは今年のバレンタインデーに GitHub 内のマークダウンファイル(.md)内にマーメイド記法で記述された部分があると、フロー図に変換して表示されるようになりました。

例えばこんな内容を含むマークダウンファイルを GitHub にコミットします(1行目はマークダウンそのものですが、3行目の ``` (バッククォート3つ)から ``` までの部分がマーメイド記法で書かれています。後述しますが、もう少し情報量を増やした書き方もあります):
2202110601

(↑なんとなくわかりますかね? AからB、AからC、BからD、CからD、という4つの流れが定義されているものです。先頭行の "graph DB;" は「フロー図を上から下(TopDown) に描く」という意味です)

そしてコミットされたファイルをブラウザで GitHub から見ると、マーメイド記法で書かれた部分がこのようにフロー図に変換されて表示されます:
2202110602



このマーメイド記法はウェブアプリケーション設計時の「画面遷移の定義」の表現に使えると思いました。例えばこんな感じのウェブアプリケーションの画面遷移を考えた時に・・・
 ・最初にログイン画面
 ・ログイン後にトップ画面
 ・トップ画面からA、B、Cの3つの画面に遷移できる

マーメイド記法だとこのように表現できると思ったのです:
```mermaid
  graph TD;
  Login --> Top;
  Top --> A;
  Top --> B;
  Top --> C;
```

また上でも少し触れたのですが、このマーメイド記法はかなり単純な最小限の情報しか含んでいませんが、もう少し情報量を増やしてこのような書き方もできます:
```mermaid
  graph TD;
  Login["ログイン"] --"/"--> Top["トップ"];
  Top --"/info"--> A["商品情報"];
  Top --"/download"--> B["ダウンロード"];
  Top --"/about"--> C["○○について"];
```


このマーメイド記法をフロー化するとこのようになります:
2022110503


A や B といったノードの名前そのままではなく、["~~"] で括られた部分がノードの表示用の名称として表示されています(一度 Top["トップ"] と表示名を定義しておくことで、2回目からはただ Top と書くだけでよくなります)。加えて矢印にも名前が付けることで、なんとなく UI のないワイヤーフレームっぽくなりました。どのページからどのページへ、なんという URL パスで進むようになるか、というのが視覚化できます(上の図の「ログイン」ページに相当する URL パスがないのでまだ不完全ですが、詳しくは後述します)。


マーメイド記法はフロー図だけでなく、色々な種類のグラフを描くことができます。ただマーメイド記法そのものの書き方についてはこのブログエントリの目的ではないので、他のサイトでの紹介を参照いただきたいです。私自身はこのページに多くお世話になりました:
https://zenn.dev/okazuki/articles/learning-mermaid


【アイデアと、実装して作ったツール】
このマーメイド記法を使って作ったファイルを使って、以下のような3つの機能を作れないだろうか、というアイデアを思いつきました:
 (1)ワイヤーフレームの全画面を表示できるようなウェブアプリ化
 (2)ワイヤーフレームの中で DB 定義が必要と思われる部分を抜き出して API 化
 (3)(おまけ)マーメイド記法で書かれた部分をフロー図化

(1)は上で示したようなフローを実現できるような最小限のウェブアプリを、マーメイド記述されたファイルから、各ページの URL パスをそのまま再現する形で自動生成する、というものです。 各ページの UI は最小限ですが、例えば上の例であれば「ログイン」ページを表示すると「トップ」ページに遷移できるようなリンクがあり、「トップ」ページを表示すると「商品情報」、「ダウンロード」、「○○について」という3つのリンクがあって、それぞれのページに繋がっている、というものです。フロー定義から画面実装までを自動化して、生成された HTML テンプレートをカスタマイズすることで見た目も定義できるようにする、というものです。

(1)についてはもう1つ、(2)にも関わるのですが例えばマーメイド記述された中に "/(複数形)""/(単数形)/:id" というフォーマットに合致する2つのパスが含まれていた場合は、前者を一覧ページ、後者を詳細ページとみなして、それに近い UI を用意する、という機能を持たせました。例えば、マーメイド記述が
```mermaid
  graph TD;
  Login["ログイン"] --"/"--> Top["トップ"];
  Top --"/users"--> A["ユーザー一覧"];
  A --"/user/:id"--> B["ユーザー"];
    :
```

のようになっていた場合、単に「ユーザー一覧」画面と「ユーザー」画面がリンクでつながっているのではなく、「「ユーザー一覧」は「複数のユーザーの一覧画面」」で「「ユーザー」画面は「ユーザー ID が :id となる単数のユーザーの詳細画面」」であることを識別できるようにしました。自動生成される画面も単なるリンクで繋げるのではなく、「ユーザー一覧」画面にはユーザーが複数表示され、それぞれのユーザーがクリックできるようになっていて、クリックするとクリックしたユーザーの詳細ページに遷移する、というものです。

そして(2)の機能は、この「ユーザー一覧」画面と「ユーザー詳細」画面があるということは「ユーザーのデータを扱う必要がある」と判断し、ユーザー情報を CRUD できるような API (と Swagger ドキュメントと DDL)を自動生成する機能です。具体的には、
 ・POST /user (一人のユーザーを新規作成する)
 ・POST /users (複数のユーザーをバルクインサートする)
 ・GET /user/:id (一人のユーザーの情報を ID を指定して取得する)
 ・GET /users (複数のユーザーの情報をまとめて取得する)
 ・PUT /user/:id (ID を指定したユーザーの情報を更新する)
 ・DELETE /user/:id (ID を指定したユーザーを削除する)
 ・DELETE /users (複数のユーザーをまとめて削除する)
という7つの CRUD API を作る、というものです。加えてこれらの API のデータ格納先となるテーブルの DDL 定義(id と name の2列だけですが・・)と、実際に動作確認できる Swagger API ドキュメントも作成します。


最後におまけの(3)、これはマーメイド記法で表記した内容を GitHub にコミットしなくても見ることができるよう、ローカルでマーメイドファイルを表示できるようにするツールもあると便利だったので、自分用に作ってみました。

こうしてできあがったのがこのツールで、現在は Node.js 向けソースコードを GitHub で公開しています:
https://github.com/dotnsf/web-template


【ツールの使い方】
このツールを使う場合は、まずは Node.js の環境を用意する必要があります。必要に応じてインストールしてください:
https://nodejs.org/ja/


次に git でソースコードを clone して、"npm install" で動作に必要なライブラリをインストールします:
$ git clone https://github.com/dotnsf/web-template
$ cd web-template
$ npm install

そしてアプリケーションや API サーバーのソースコードを生成するためのマーメイドファイルを用意します。ソースコード内に mermaid_sample.md というファイルが含まれていますので、これをそのまま使っても構いませんし、自分で用意しても構いません。

ただ自分でマークダウンファイルを用意する場合は次の点に注意してください:
  • 各ノード(ページ)の表示名を定義する場合は ["~~"] という形で記述する(マーメイドのルールでは ("~~") など、丸括弧で括っても正しく判断されますが、このツールを使う場合は ["~~"] という四角括弧で表示名を括ってください。
  • 全てのノート(ページ)を表示するための URL パスが定義できているようにマーメイドファイルを用意してください。

例えば上で紹介したこのマーメイドファイル例:
```mermaid
  graph TD;
  Login["ログイン"] --"/"--> Top["トップ"];
  Top --"/info"--> A["商品情報"];
  Top --"/download"--> B["ダウンロード"];
  Top --"/about"--> C["○○について"];
```

は一番上にある Login["ログイン"] ページを表示するための URL がどこにも定義されていません(ので、このまま実行してもエラーになります)。マーメイドファイルのどこかに(例えば以下の例のように)このログインページへの URL パスを追加する必要があります(mermaid_sample.md ファイルは初めからこのようになっています):
```mermaid
  graph TD;
  Login["ログイン"] --"/"--> Top["トップ"];
  Top --"/info"--> A["商品情報"];
  Top --"/download"--> B["ダウンロード"];
  Top --"/about"--> C["○○について"];
  Top --"/login"--> Login;
```

最後にトップページからログインページに遷移するためのパス /login を定義する行を加えました。これで全てのノード(ページ)の URL パスが定義されたことになります。もし実際のアプリケーションではトップページからログインページへのリンクが不要であれば、生成されたトップページからログインページへのリンクボタンを手動で削除してください(具体的には以下で説明します)。

なお最初の状態のマーメイドサンプルファイル(mermaid_sample.md)の内容は以下のようになっています:
# mermaid

```mermaid
  graph TD;
      Login["ログイン"] --"/"--> Top["トップ"];
      Top --"/items"--> Items["アイテム一覧"];
      Items --"/item/:id"--> Item["アイテム詳細"];
      Top --"/users"--> Users["ユーザー一覧"];
      Users --"/user/:id"--> User["ユーザー詳細"];
      Top --"/about"--> About["サイト解説"];
      Top --"/login"--> Login;
```

「アイテム一覧(/items)」と「アイテム詳細(/item/:id)」、「ユーザー一覧(/users)」と「ユーザー詳細(/user/:id)」という組み合わせが定義されていることを覚えておいてください。

また、このフローをマーメイド対応のビューワで表示すると、このようになります:
2022110504


マーメイドファイルが用意できたら実際に動かしてみましょう。まず(1)のワイヤーフレームの全画面を表示できるようなウェブアプリを作ってみます。この場合はソースコード内の web.js を使って、以下のように実行します:
$ MERMAID=mermaid_sample.md node web

実行時に MERMAID という環境変数を指定しています。この環境変数にマーメイドファイル名を指定します(上の例では mermaid_sample.md ファイルを指定しています)。

マーメイドファイルに問題もなく、正しく実行された場合は一瞬で実行が完了し、web/ というフォルダに実行結果が生成されています。実際に生成された結果を確認するには web/ フォルダで "npm start" を実行します:
$ cd web
$ npm install
$ npm start

成功すると 8080 番ポートでウェブアプリケーションが待ち受けているので実際にアクセスして動作を確認してみましょう。まずログインページにアクセスするには(マーメイドファイル内で)/login へアクセスすることでログインページが表示されるよう定義していたので、ウェブブラウザを起動して "http://localhost:8080/login" にアクセスしてみます:
2022110505


本来であれば「ログイン」ページには ID とパスワードを入力するフィールドがあって、、というものだと思いますが、残念ながらそこまでは再現できていません。ただこのページには「トップ」と書かれたボタンがあり、このボタンをクリックすることで(マーメイドファイルの中で定義されていたように)トップページへ遷移するようにできています:
2022110506


トップページは↑のようになります。マーメイドファイルではトップページから「アイテム一覧(/items)」、「ユーザー一覧(/users)」、「サイト解説(/about)」、「ログイン(/login)」という4つのページへのリンクが定義されていたので、それらがそのまま4つのボタンになっています。正しく再現できています。

試しに「アイテム一覧」ボタンをクリックすると以下のようになります:
2022110507


先ほどまでのページとは少し違う画面になりました。これはアイテム一覧のページ(/items) がアイテム詳細(/item/:id) のページと繋がっていて、これらの URL パスのルール性から「個別のページ」ではなく「item の一覧」のページであると判定された結果です。その結果、表形式で item の一覧(id と名前だけですけど)が表示されています。そしてこれらのいずれかをクリックすると(例えば id = 0 の一番上のデータをクリックすると)/item/0 へ遷移し、詳細画面が表示されます(トップ画面からユーザー一覧ボタンをクリックした場合も同様の画面遷移となります):
2022110508

※(注意)
この「一覧」と「詳細」の両ページの存在を確認するには、マーメイドファイル内の URL パスで
- /(複数形)
- /(単数形)/:id
という2つの URL パスが定義されていることが条件なのですが、この「複数形」の表現には注意が必要です。

"user" の複数形は "users" で、"item" の複数形は "items" で何も問題はないのですが、例えば "category" の複数形は注意が必要です。英単語として正しくは "categories" となりますが、本ツールでは単に "s" を付けるだけの "categorys" と定義する必要があります。"information" も(正しくは複数形が存在しない英単語ですが、もし information の一覧ページを作りたいのであれば)"/informations" という URL パスで一覧ページを定義する必要がある、という点に注意してください。
※(注意ここまで)


一方、トップ画面から「サイト解説」や「ログイン」ボタンをクリックした場合は、遷移先が一般的なページ画面であると認識され、表形式ではなく(リンクがある場合は)ボタンが表示される画面となります(下図は「サイト解説」ボタンを押した場合):
2022110509


・・・と、このように web.js はマーメイドファイルを指定するだけで、その内容からここまでのページ遷移を実現するウェブアプリケーションが自動生成できました。実際に詳細なワイヤーフレーム画面を作りたい場合は生成されたフォルダの views サブフォルダや public サブフォルダに HTML テンプレートや CSS, JavaScript ができているので、これらをカスタマイズすることでデフォルトの生成画面を(HTML や CSS の知識だけで)カスタマイズできる、というものです。


次に同じマーメイドファイルから(2)の API を作ってみます。(1)でも紹介しましたが、今回使用するマーメイドファイルには「ユーザー(user)」と「アイテム(item)」という2つのデータを対象に一覧表示したり、詳細表示するページが含まれていました。ということは user と item の2つはデータベースに格納して読み書き更新削除する可能性があるデータ、という推測ができることになります。

この推測通りに動くかどうかを実際に使って確認してみます。元の web-template フォルダで今度は api.js を以下のように実行します:
$ MERMAID=mermaid_sample.md node api

この実行結果は api/ フォルダに出力されます。今度も(1)と同様に api/ フォルダに生成されたコードを実行してみます:
$ cd api
$ npm install
$ npm start

成功すると 8081 番ポートで API アプリケーションが待ち受けており、また /_doc/ という URL パスで Swagger ドキュメントが稼働しています。実際に Swagger にアクセスして動作を確認してみましょう。"http://localhost:8081/_doc" にアクセスしてみます:
2022110510

2022110511


↑のように、item および user の情報を CRUD できる API と、その Swagger ドキュメントが用意されました。データはメモリに格納するので再起動するまでの間であれば実際にデータを保存したり、変更したり、削除したり、読み出したりすることができます。マーメイドファイルからデータ操作が必要な要素を見つけ出して API 化する(ためのソースコードを出力する)、という機能が実現できていることがわかります。 プロトタイピング目的であればこれだけでもかなり使えるところまで設計を可視化することができると思っていますが、(1)で紹介した web.js でマーメイドファイルからページ遷移機能と、(2)で紹介した api.js で API サーバーを両方作った上で、一覧ページと詳細ページの部分だけ API 連携するようカスタマイズすれば、細かな見た目以外のかなりの部分を実現できるプロトタイピングがほぼノーコード/ローコードで実現できると感じています。


最後におまけの(3)について紹介します。(3)はカスタマイズしたマーメイドファイルが、想定していた通りの正しいフローになっているかどうかを確認するためのマーメイド・プレビューワーとしてのアプリケーションです。(1)・(2)同様に環境変数 MERMAID にマーメイドファイルを指定して、以下のように実行します:
$ MERMAID=mermaid_sample.md node preview

成功すると 8000 番ポートでプレビューワーのアプリケーションが待ち受けています。実際にアクセスして動作を確認してみましょう。"http://localhost:8000" にアクセスしてみます:
2022110512


マーメイドファイルのプレビューができました。これで正しい(自分の想定通りの)ワイヤーフレームがマーメイドファイルとして実現できているかどうかを(GitHub などにコミットしなくても)事前に確認することができます。おまけツールではありますが、(1)や(2)を実行する前に何度か使うことになる利用頻度の高いツールであるとも思っています。


【まとめ】
もともとはウェブアプリのデザインとワイヤーフレームを効率よく作るためのプロトタイピングツールを作ろうとしていたのですが、マーメイドファイルとの相性がよく、データ API まで作れるようになったことで、ノーコード/ローコードツールともいえるかな、という形になりました。実際にはここで紹介していないパラメータを使うことで CRUD API を本物のデータベースと接続して作ったり、UI 部分も(デフォルトでは Bootstrap ベースで作るのですが)Carbon や Material デザインにしたり、ということもできるようには作っています。 興味あるかたは公開されているソースコードや README を見て試してみてください。

以前からなんとなくこの挙動に気付いてはいたのですが、データを受け取る側で加工することで回避できていたので真剣に原因や対処を考えていませんでした。今回とある機能をライブラリ化することになり、「受け取る側ではなく、送る側で対処が必要」になったので真面目に調査して、対処法含めて分かったのでブログに残しておくことにしました。

現象はこのブログエントリのタイトル通りなのですが、まず「何をするとどうなるか」を紹介します。例えば jQuery を使ったこんな内容のコードを実行したとします:
$.ajax({
  url: '/api/item',
  type: 'POST',
  data: { name: 'シャンプー', price: 1000 },
  success: function( result ){
    :
  },
  error: function( err, text, message ){
    :
  }
});

Ajax を使って /api/item に POST リクエストを実行する、という内容です。その際に { name: 'シャンプー', price: 1000 } という JSON データを送信しています。

これを以下のような Node.js のコードで受け取った場合を想定してみます(Node.js はあくまでコードの例であって、Node.js じゃなくても同じ現象が起こります):
var express = require( 'express' ),
    bodyParser = require( 'body-parser' ),
    app = express();

app.use( bodyParser.urlencoded( { extended: true } );
app.use( bodyParser.json() );

  :

app.post( '/api/item', function( req, res ){
  var data = req.body;
  console.log( data );

    :
});



Node.js ではよく使う方法ですが、Express (と body-parser)を使って "/api/item" に POST されたデータを受け取っています("var data = req.body;")。この例では受け取った内容をそのままコンソールに表示しています("console.log( data );")。

先ほどの POST データであれば、コンソール画面には
{ name: "シャンプー", price: 1000 }

という JSON データが表示されるような気がしますが、実際には
{ name: "シャンプー", price: "1000" }

という、price の値が送信した時の数値ではなく、文字列に変換されて送信されます。これが本ブログエントリのタイトルにも書いた『jQuery の $.ajax で JSON データを POST すると整数が文字列になる??』という現象です。

送る側だけでなく、受け取る側も自分達が実装しているのであれば受け取った JSON データの price の値を数値に変換するという手もあります:
//. data.price が文字列だった場合は数値に変換する
if( typeof data.price == 'string' ){
  data.price = parseInt( data.price ); 
}

最悪、この方法で対処できるかもしれませんが、受け取る側を変更できないという前提にした場合、この方法は使えなくなります。つまり「正しいフォーマットで送信する」必要がでてきます。

で、いろいろ調べた結果として、jQuery の Ajax 実行部を以下のように変更することで JSON データ内のフォーマットを壊さずに、JSON データのまま送信することができるようでした:
$.ajax({
  url: '/api/item',
  type: 'POST',
  contentType: 'application/json',
  dataType: 'json',
  data: JSON.stringify( { name: 'シャンプー', price: 1000 } ),
  success: function( result ){
    :
  },
  error: function( err, text, message ){
    :
  }
});

先ほどの例と違う部分を赤字にしていますが、要するに、
  • contentType: 'application/json' を追加する
  • dataType: 'json' を追加する
  • 送信する JSON データ全体を JSON.stringify() で文字列化する
という3つの変更を加えることでそのままのフォーマットで(受信側でも price は文字列の '1000' ではなく、整数の 1000 として)送信することができるようでした。


そういえば以前はこのスタイルで送っていたような気がしつつ、よりシンプルな方法でも(データ型が乱れるだけで)送れることに気付いて、それから省略形で送ってしまっていたような気がします。その結果、データのフォーマットがおかしくなっていた(が、あまり気にしなかった)ということだと思っています。 ともあれ、これで受け取る側を変更しなくても、正しいデータフォーマットのままで送信することができそうです。

jQuery の場合「正確に記述しなくてもある程度できちゃう」から、正確でなかった今までの方法が正しいと勘違いしていたようです。で、足りない部分もちゃんと記述すればできる、と。いい勉強になりました。



このページのトップヘ