以前からなんとなくこの挙動に気付いてはいたのですが、データを受け取る側で加工することで回避できていたので真剣に原因や対処を考えていませんでした。今回とある機能をライブラリ化することになり、「受け取る側ではなく、送る側で対処が必要」になったので真面目に調査して、対処法含めて分かったのでブログに残しておくことにしました。
現象はこのブログエントリのタイトル通りなのですが、まず「何をするとどうなるか」を紹介します。例えば jQuery を使ったこんな内容のコードを実行したとします:
Ajax を使って /api/item に POST リクエストを実行する、という内容です。その際に { name: 'シャンプー', price: 1000 } という JSON データを送信しています。
これを以下のような Node.js のコードで受け取った場合を想定してみます(Node.js はあくまでコードの例であって、Node.js じゃなくても同じ現象が起こります):
Node.js ではよく使う方法ですが、Express (と body-parser)を使って "/api/item" に POST されたデータを受け取っています("var data = req.body;")。この例では受け取った内容をそのままコンソールに表示しています("console.log( data );")。
先ほどの POST データであれば、コンソール画面には
という JSON データが表示されるような気がしますが、実際には
という、price の値が送信した時の数値ではなく、文字列に変換されて送信されます。これが本ブログエントリのタイトルにも書いた『jQuery の $.ajax で JSON データを POST すると整数が文字列になる??』という現象です。
送る側だけでなく、受け取る側も自分達が実装しているのであれば受け取った JSON データの price の値を数値に変換するという手もあります:
最悪、この方法で対処できるかもしれませんが、受け取る側を変更できないという前提にした場合、この方法は使えなくなります。つまり「正しいフォーマットで送信する」必要がでてきます。
で、いろいろ調べた結果として、jQuery の Ajax 実行部を以下のように変更することで JSON データ内のフォーマットを壊さずに、JSON データのまま送信することができるようでした:
先ほどの例と違う部分を赤字にしていますが、要するに、
そういえば以前はこのスタイルで送っていたような気がしつつ、よりシンプルな方法でも(データ型が乱れるだけで)送れることに気付いて、それから省略形で送ってしまっていたような気がします。その結果、データのフォーマットがおかしくなっていた(が、あまり気にしなかった)ということだと思っています。 ともあれ、これで受け取る側を変更しなくても、正しいデータフォーマットのままで送信することができそうです。
jQuery の場合「正確に記述しなくてもある程度できちゃう」から、正確でなかった今までの方法が正しいと勘違いしていたようです。で、足りない部分もちゃんと記述すればできる、と。いい勉強になりました。
現象はこのブログエントリのタイトル通りなのですが、まず「何をするとどうなるか」を紹介します。例えば 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() で文字列化する
そういえば以前はこのスタイルで送っていたような気がしつつ、よりシンプルな方法でも(データ型が乱れるだけで)送れることに気付いて、それから省略形で送ってしまっていたような気がします。その結果、データのフォーマットがおかしくなっていた(が、あまり気にしなかった)ということだと思っています。 ともあれ、これで受け取る側を変更しなくても、正しいデータフォーマットのままで送信することができそうです。
jQuery の場合「正確に記述しなくてもある程度できちゃう」から、正確でなかった今までの方法が正しいと勘違いしていたようです。で、足りない部分もちゃんと記述すればできる、と。いい勉強になりました。