PHPのjson_encode関数に問題があります。数値を文字列としてエンコードします。
array('id' => 3)
なる
"{ ["id": "3", ...)
jsはこれらの値を検出すると、それらを文字列として解釈し、数値演算が失敗します。json_encode
数値を文字列としてエンコードしないようにする方法を知っている人はいますか?ありがとうございました!
PHPのjson_encode関数に問題があります。数値を文字列としてエンコードします。
array('id' => 3)
なる
"{ ["id": "3", ...)
jsはこれらの値を検出すると、それらを文字列として解釈し、数値演算が失敗します。json_encode
数値を文字列としてエンコードしないようにする方法を知っている人はいますか?ありがとうございました!
回答:
私は非常に簡単なテストを行いました:
$a = array(
'id' => 152,
'another' => 'test',
'ananother' => 456,
);
$json = json_encode($a);
echo $json;
私が間違っていなければ、これはあなたが説明しているように思えますか?
そして、私は出力として得ています:
{"id":152,"another":"test","ananother":456}
したがって、この場合、整数は文字列に変換されていません。
それでも、これは使用しているPHPのバージョンに依存している可能性があります。PHPのバージョンに応じて、json_encodeに関連するいくつかのバグが修正されています...
このテストはPHP 5.2.6で行われました。PHP 5.2.9と5.3.0でも同じ結果が得られます。テストする別の5.2.xバージョンはありませんが、:-(
PHPのどのバージョンを使用していますか?それとも、あなたのテストケースはあなたが投稿した例よりも複雑ですか?
多分1つのバグレポート http://bugs.php.net/が関連している可能性がありますか?たとえば、Bug#40503:json_encode整数変換がPHPと矛盾していますか?
たぶんバグ#38680もあなたに興味がありますか?
PHP 5.3.3以降、数値を自動変換するためのフラグがあることに注意してください(optionsパラメーターはPHP 5.3.0で追加されました)。
$arr = array( 'row_id' => '1', 'name' => 'George' );
echo json_encode( $arr, JSON_NUMERIC_CHECK ); // {"row_id":1,"name":"George"}
JSON_NUMERIC_CHECK
文字列を解析しようとして、文字列が数値かどうかを自動的に推測しようとします。あなたがそれについて考えるならば、それはかなり信頼できません。数値のように見えるすべてのプロパティを(必要なプロパティだけでなく)数値に変換し、数値のように見える場合にのみそれを行います。安全ではないにしても、それは少なくとも不安定です。生成されたJSONを使用するコードは、どちらか一方のタイプに依存する場合があります。これらの期待が満たされない場合、奇妙なことが起こります。適切な方法と安全性を重視する場合は、必要な値を選択的に変換する必要があります。
私も同様にDB(PostgreSQL)から読み込んでおり、すべて文字列でした。各行をループし、それを使って最終的な結果配列を構築するため、
$result_arr[] = array($db_row['name'], (int)$db_row['count']);
ループ内で強制的に整数値にします。これを行うjson_encode($result_arr)
と、数値として正しくフォーマットされます。これにより、データベースからの数字とそうでない数字を制御できます。
編集:
このjson_encode()
関数には、JSON_NUMERIC_CHECK
フラグを2番目の引数として使用して、その場でこれを実行する機能もあります。ドキュメントのこのユーザーの例に示されているように(下にコピー)、それを使用する場合は注意が必要です。http://uk3.php.net/manual/en/function.json-encode.php#106641
<?php
// International phone number
json_encode(array('phone_number' => '+33123456789'), JSON_NUMERIC_CHECK);
?>
そして、あなたはこのJSONを取得します:
{"phone_number":33123456789}
json_encode
関数ではなく、データ型を解釈しないDBアダプターにあるようです。これが最も正しい答えですが、JSON_NUMERIC_CHECK
電話番号やその他の数値文字列値も変換するので注意してください。これにより、先行ゼロまたは「+」に問題が発生する可能性があります... DB読み取り機能でこの問題を修正することをお勧めします。
試す
$arr = array('var1' => 100, 'var2' => 200);
$json = json_encode( $arr, JSON_NUMERIC_CHECK);
ただし、PHP 5.3.3でのみ機能します。このPHP json_encode変更ログを確認してください http://php.net/manual/en/function.json-encode.php#refsect1-function.json-encode-changelog
同じ問題が発生しています(PHP-5.2.11 / Windows)。この回避策を使用しています
$json = preg_replace( "/\"(\d+)\"/", '$1', $json );
引用符で囲まれたすべての(非負の整数)数値を数値自体に置き換えます( '"42"'は '42'になります)。
PHPマニュアルのこのコメントも参照してください。
$json_array = json_encode($some_array, false);
したがって、false引数はPHPにオブジェクト変換を行わないように指示します。
json_encode(array(-1=>'que', '0'=>'-1'))
$this->data = preg_replace("/\" *?: *?(\d+)/", '":"$1"', $this->data);
次のテストでは、タイプを文字列に変更すると、json_encode()が数値をJSON文字列として(つまり、二重引用符で囲まれて)返すことを確認します。settype(arr ["var"]、 "integer")またはsettype($ arr ["var"]、 "float")を使用して修正してください。
<?php
class testclass {
public $foo = 1;
public $bar = 2;
public $baz = "Hello, world";
}
$testarr = array( 'foo' => 1, 'bar' => 2, 'baz' => 'Hello, world');
$json_obj_txt = json_encode(new testclass());
$json_arr_txt = json_encode($testarr);
echo "<p>Object encoding:</p><pre>" . $json_obj_txt . "</pre>";
echo "<p>Array encoding:</p><pre>" . $json_arr_txt . "</pre>";
// Both above return ints as ints. Type the int to a string, though, and...
settype($testarr["foo"], "string");
$json_arr_cast_txt = json_encode($testarr);
echo "<p>Array encoding w/ cast:</p><pre>" . $json_arr_cast_txt . "</pre>";
?>
完全を期すために(まだコメントを追加できないため)、この詳細を別の回答として追加します。
(編集:ソースデータ(つまり、OPの場合は、データベースの結果セット)が問題である可能性があることを理解してから読み取る(数値列を文字列として返すことにより)、実際にはjson_encode()は問題の原因ではありませんでした)
両方のmysql_fetch_arrayのマニュアルページ:
取得した行に対応する文字列の配列を返します。
...および " mysql_ fetch_ row ":
フェッチされた行に対応する文字列の数値配列を返します
明確に述べている; 返される配列のエントリは文字列になります。
(私はphpBB2でDBクラスを使用していました(そうです、それは廃止されました!)、そしてそのクラスの "sql_fetchrow()"メソッドは "mysql_fetch_array()"を使用しています)
それに気づかなかったので、私もこの質問を見つけて問題を理解することになりました。:)
Pascal Martinが彼のフォローアップコメントで上記で述べたように、ソースでの「不正なタイプ」の問題に対処する解決策(つまり、「mysql_field_type()」関数を使用し、フェッチの直後にキャストを実行する(または「オブジェクト」のような他のフェッチメソッド?))は一般的に良いでしょう。
そのため、Pascal MARTINはここで十分なクレジットを得ていません。JSONが返されるたびに数値を確認することは、何百ものサーバー側関数を持つ既存のプロジェクトでは実行できません。
php-mysqlをphp-mysqlndに置き換えたところ、問題は解消しました。数値は数値、文字列は文字列、ブール値はブール値です。
json_encodeは、データ構造をJSON形式でシリアル化し、ネットワーク経由で送信します。したがって、すべてのコンテンツは文字列型になります。$ _POSTまたは$ _GETからパラメーターを受け取るときと同じです。
送信された値に対して数値演算を行う必要がある場合は、まずそれらをintに変換し( PHPのintval()関数またはJavascriptのparseInt()を使用)、次に演算を実行します。
PHP json_encode()は文字列を返します。
ただし、jsコードでparseFloat()またはparseInt()を使用できます。
parseFloat('122.5'); // returns 122.5
parseInt('22'); // returns 22
parseInt('22.5'); // returns 22
oli_arborumが言ったように、私はあなたがpreg_replace
仕事をするために使うことができると思います。次のようにコマンドを変更するだけです。
$json = preg_replace('#:"(\d+)"#', ':$1', $json);