PHP nomor enkode json_encode sebagai string

142

Saya mengalami satu masalah dengan fungsi PHP json_encode. Ini mengkodekan angka sebagai string, misalnya

array('id' => 3)

menjadi

"{ ["id": "3", ...)

Ketika js menemukan nilai-nilai ini, itu menafsirkannya sebagai string dan operasi numerik gagal pada mereka. Adakah yang tahu cara mencegah json_encodepenyandian angka sebagai string? Terima kasih!

Chris Barnhill
sumber
Ternyata ini adalah masalah khusus versi. Terkadang tarikan dari basis data MySql akan mempertahankan jenis yang benar. Dalam versi yang lebih lama, ini dapat mengembalikan semuanya sebagai string. Saya menulis tentang hal itu pagi ini. shakyshane.com/blog/output-json-from-php.html
shane
1
Saya mengalami masalah yang sama dan saya dapat menyelesaikan masalah saya menggunakan Laravel's Mutators dalam Model. Ini memungkinkan Anda mengubah nilai-nilai dalam model. laravel.com/docs/eloquent#accessors-and-mutators Saya awalnya tidak mengerti, tetapi pertanyaan ini membantu: stackoverflow.com/questions/16985656/…
Jazzy

Jawaban:

28

Saya telah melakukan tes yang sangat cepat:

$a = array(
    'id' => 152,
    'another' => 'test',
    'ananother' => 456,
);
$json = json_encode($a);
echo $json;

Ini sepertinya seperti apa yang Anda gambarkan, jika saya tidak salah?

Dan saya mendapatkan sebagai output:

{"id":152,"another":"test","ananother":456}

Jadi, dalam hal ini, bilangan bulat belum dikonversi ke string.


Namun, ini mungkin tergantung dari versi PHP yang kami gunakan: ada beberapa bug terkait json_encode yang diperbaiki, tergantung pada versi PHP ...

Tes ini telah dilakukan dengan PHP 5.2.6; Saya mendapatkan hal yang sama dengan PHP 5.2.9 dan 5.3.0; Saya tidak memiliki versi 5.2.x lain untuk diuji, meskipun :-(

Versi PHP apa yang Anda gunakan? Atau apakah test case Anda lebih kompleks dari contoh yang Anda posting?

Mungkin satu laporan bug di http://bugs.php.net/ dapat dikaitkan? Misalnya, Bug # 40503: konversi integer json_encode tidak konsisten dengan PHP ?


Mungkin Bug # 38680 juga bisa membuat Anda tertarik, btw?

Pascal MARTIN
sumber
Terima kasih Martin. Saya menggunakan 5.2.9. Saya ingin tahu apakah data numerik semakin dibaca dari db sebagai string? Saya yakin tipe bidangnya int, tapi saya tidak bisa memikirkan penjelasan lain. Saya akan mencoba tes cepat Anda pada sistem saya dan melihat apakah saya mendapatkan hasil yang sama.
Chris Barnhill
12
OK tentang 5.2.9; jika data Anda berasal dari basis data, masalahnya mungkin ada di sana: Saya sering melihat data berasal dari basis data dengan segala yang dilemparkan ke string (Saya sudah melihat ini dengan PDO dan mssql; tetapi, jika saya ingat dengan benar, ini juga terjadi untuk MySQL dalam PHP <5.3, ketika driver mysqlnd baru belum ada); untuk memeriksa seperti apa data Anda, Anda dapat menggunakan var_dump, yang menampilkan tipe setiap bagian data.
Pascal MARTIN
(lanjutan) berpikir tipe data untuk nilai numerik adalah string? Ada ide?
Chris Barnhill
1
Saya tidak tahu persis alasan teknis "mengapa data dikembalikan dari MySQL sebagai string"; mungkin ada hubungannya dengan driver antara PHP dan MySQL; itu adalah sesuatu yang (setidaknya dalam beberapa kasus) dikoreksi oleh driver mysqlnd baru yang dilengkapi dengan PHP 5.3 (lihat blog.ulf-wendel.de/?p=184 ; cari "integer" di halaman untuk menemukan yang menarik kalimat) ;; tapi saya setuju bahwa ini tidak baik ^^
Pascal MARTIN
Tidak masalah bahwa data numerik yang dikembalikan oleh json_encode () tidak dalam tanda kutip, masih berupa string. Nilai kembali dari fungsi json_encode () adalah string. Mengenai MySQL mengembalikan semua bidang sebagai string, ya saya juga mengalami ini dengan PDO. Cara saya melihatnya Anda harus selalu memberikan nilai yang Anda harapkan menjadi numerik ke integer (atau float) dalam PHP untuk memastikan, jangan percaya MySQL atau database lain untuk mengembalikan nilai dengan tipe yang benar.
Richard Knop
352

Perhatikan bahwa sejak PHP 5.3.3, ada bendera untuk angka konversi otomatis (parameter opsi ditambahkan dalam PHP 5.3.0):

$arr = array( 'row_id' => '1', 'name' => 'George' );
echo json_encode( $arr, JSON_NUMERIC_CHECK ); // {"row_id":1,"name":"George"}
Rijk
sumber
4
Perhatikan bahwa JSON_NUMERIC_CHECK membutuhkan PHP 5.3.3.
Robert
10
Bekerja dengan sempurna sampai ia melemparkan label numerik ke integer, meledakkan .toLowerCase () di IE. Hati-hati, solusi ini sederhana tetapi terlalu bersemangat.
Brad Koch
6
ANDA ADALAH PAHLAWAN SAYA menyukainya.
Petrogad
5
Ini memiliki beberapa efek samping jika string Anda bukan angka tetapi konten seperti ini: 5252788e16597. referensi: bugs.php.net/bug.php?id=64695
TonyQ
20
JSON_NUMERIC_CHECKmencoba menebak secara otomatis apakah string adalah angka atau tidak dengan mencoba menguraikannya. Itu sangat tidak bisa diandalkan jika Anda memikirkannya. Ini akan mengonversi semua properti yang tampak numerik menjadi angka (tidak hanya yang Anda inginkan) dan hanya akan melakukannya jika terlihat seperti angka. Setidaknya goyah jika tidak aman. Kode yang mengkonsumsi JSON yang dihasilkan mungkin bergantung pada jenis yang satu atau yang lain. Hal-hal aneh bisa terjadi jika harapan itu tidak terpenuhi. Jika Anda peduli dengan praktik dan keselamatan yang baik, Anda harus secara selektif mengonversi nilai yang Anda inginkan.
wadim
35

Saya, juga membaca dari DB (PostgreSQL) dan semuanya adalah string. Kami mengulangi setiap baris dan melakukan hal-hal dengannya untuk membangun array hasil akhir kami, jadi saya gunakan

$result_arr[] = array($db_row['name'], (int)$db_row['count']);

dalam loop untuk memaksanya menjadi nilai integer. Kapan saya melakukannyajson_encode($result_arr) sekarang, itu memformatnya dengan benar sebagai angka. Ini memungkinkan Anda untuk mengontrol nomor yang berasal dan bukan dari basis data Anda.

EDIT:

The json_encode()Fungsi juga memiliki kemampuan untuk melakukan hal ini dengan cepat menggunakan JSON_NUMERIC_CHECKbendera sebagai argumen kedua untuk itu. Anda harus berhati-hati menggunakannya seperti yang ditunjukkan dalam contoh pengguna ini dalam dokumentasi (disalin di bawah): http://uk3.php.net/manual/en/function.json-encode.php#106641

<?php
// International phone number
json_encode(array('phone_number' => '+33123456789'), JSON_NUMERIC_CHECK);
?>

Dan kemudian Anda mendapatkan JSON ini:

{"phone_number":33123456789}
Mouckatron
sumber
ya, tampaknya masalahnya adalah adaptor DB yang tidak menginterpretasikan tipe data, BUKAN json_encodefungsi. ini adalah jawaban yang paling benar, tetapi berhati-hatilah karena JSON_NUMERIC_CHECKmengkonversi juga nomor telepon dan nilai string numerik lainnya, dan ini dapat memberikan masalah dalam memimpin nol atau '+' ... Saya sarankan untuk memperbaiki masalah ini dalam fungsi membaca DB.
caesarsol
8

mencoba $arr = array('var1' => 100, 'var2' => 200);
$json = json_encode( $arr, JSON_NUMERIC_CHECK);

Tetapi itu hanya bekerja pada PHP 5.3.3. Lihatlah PHP ini json_encode change log http://php.net/manual/en/function.json-encode.php#refsect1-function.json-encode-changelog

habibillah
sumber
Ini berhasil untuk saya. Instalasi default PHP + apache pada debian squeeze 6.0.5 dengan data yang berasal dari postgre db
Nikolay Spassov
7

Saya mengalami masalah yang sama (PHP-5.2.11 / Windows). Saya menggunakan solusi ini

$json = preg_replace( "/\"(\d+)\"/", '$1', $json );

yang menggantikan semua angka (non-negatif, bilangan bulat) yang dilampirkan dalam tanda kutip dengan angka itu sendiri ('"42"' menjadi '42').

Lihat juga komentar ini dalam manual PHP .

oli_arborum
sumber
Terima kasih untuk kodenya, tetapi sayangnya itu tidak berfungsi pada json saya karena saya memiliki nomor sebagai nama objek, dan tampaknya membuat json tidak valid :(
SSH
@ SSHT, ini, mungkin Anda harus menggunakan sintaks ini untuk mengubah array menjadi array yang dikodekan JSON dan bukan objek. $json_array = json_encode($some_array, false);Jadi argumen palsu memberitahu PHP untuk tidak melakukan konversi objek.
hyde
Sama sekali tidak aman untuk menggunakan solusi itu. Anda akan mendapatkan json yang tidak valid dengan struktur seperti itu:json_encode(array(-1=>'que', '0'=>'-1'))
Alex Yaroshevich
Saya punya masalah sebaliknya, saya membutuhkan integer saya dikodekan sebagai string dalam PHP 7.0 dan menggunakan ini$this->data = preg_replace("/\" *?: *?(\d+)/", '":"$1"', $this->data);
Maciej Swic
Saya akan mengubah regex asli menjadi `" /\"(#d+\.?\d*)"" "" untuk memasukkan desimal, catatan lain adalah bahwa orang-orang yang menggunakan JSON_NUMERIC_CHECK akan menghadapi masalah ketika string juga benar. nomor dalam notasi ilmiah. misalnya, 19E008. JSON_NUMERIC_CHECK akan mengonversinya menjadi 190000 ...
Sahib Khan
3

Tes berikut ini mengonfirmasi bahwa mengubah jenis ke string menyebabkan json_encode () mengembalikan numerik sebagai string JSON (yaitu, dikelilingi oleh tanda kutip ganda). Gunakan settype (arr ["var"], "integer") atau settype ($ arr ["var"], "float") untuk memperbaikinya.

<?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>";

?>
Jay Andrew Allen
sumber
2

Demi kelengkapan (karena saya belum dapat menambahkan komentar), izinkan saya juga menambahkan detail ini sebagai jawaban lain:

(Sunting: Dibaca setelah menyadari bahwa data sumber (yaitu dalam kasus OP, kumpulan hasil basis data) dapat menjadi masalah (dengan mengembalikan kolom numerik sebagai string), dan json_encode () sebenarnya bukan sumber masalah)

Halaman manual dari " mysql_fetch_array ":

Mengembalikan array string yang sesuai dengan baris yang diambil,

... dan " baris mysql_ fetch_ ":

Mengembalikan array numerik string yang sesuai dengan baris yang diambil

dengan jelas menyatakan bahwa; entri dalam array yang dikembalikan adalah string.

(Saya menggunakan kelas DB di phpBB2 (ya saya tahu, ini sudah usang!), Dan metode "sql_fetchrow ()" dari kelas itu menggunakan "mysql_fetch_array ()")

Tidak menyadarinya, saya akhirnya menemukan pertanyaan ini, dan memahami masalahnya! :)

Seperti yang dikatakan Pascal Martin di atas dalam komentar tindak lanjutnya, saya percaya solusi yang menangani masalah "tipe salah" pada sumbernya (yaitu dengan menggunakan fungsi " mysql_field_type () " dan melakukan casting tepat setelah mengambil, (atau metode pengambilan lainnya seperti "objek"?)) akan menjadi lebih baik secara umum.

OzgurH
sumber
2

Begitu Pascal MARTIN tidak mendapatkan kredit yang cukup di sini. Memeriksa nilai numerik pada setiap pengembalian JSON tidak cocok untuk proyek yang ada dengan ratusan fungsi sisi server.

Saya mengganti php-mysql dengan php-mysqlnd, dan masalahnya hilang. Angka adalah angka, string adalah string, booleans adalah boolean.

Rory Jarrard
sumber
0

Saya juga punya masalah yang sama saat memproses data dari database. Pada dasarnya masalahnya adalah bahwa jenis dalam array untuk mengkonversi di json, dikenali oleh PHP sebagai string dan bukan sebagai integer. Dalam kasus saya, saya membuat kueri yang mengembalikan data dari baris penghitungan kolom DB. Driver PDO tidak mengenali kolom sebagai int, tetapi sebagai string. Saya dipecahkan dengan melakukan pemeran sebagai int di kolom yang terpengaruh.

balucio
sumber
0
$rows = array();
while($r = mysql_fetch_assoc($result)) {
    $r["id"] = intval($r["id"]); 
    $rows[] = $r;
}
print json_encode($rows);  
Yar
sumber
0

itu adalah versi php masalahnya, memiliki masalah yang sama memutakhirkan versi php saya ke 5.6 menyelesaikan masalah

Peter Allen
sumber
0

Melemparkan nilai ke int atau float sepertinya memperbaikinya. Sebagai contoh:

$coordinates => array( 
    (float) $ap->latitude,
    (float) $ap->longitude 
);
Derrick Miller
sumber
0

Anda dapat menggunakan (int) jika ada masalah !! Ini akan bekerja dengan baik.

Rahul Gupta
sumber
-1

Hanya mengalami masalah yang sama dan database mengembalikan nilai sebagai string.

Saya menggunakan ini sebagai solusinya:

$a = array(
    'id' => $row['id'] * 1,
    'another' => ...,
    'ananother' => ...,
);
$json = json_encode($a);

Yaitu mengalikan nilainya dengan 1 untuk memasukkannya ke dalam angka

Semoga itu bisa membantu seseorang

Leon
sumber
menggunakan pengganda bukanlah solusi yang paling efisien. pertimbangkan untuk menggunakan JSON_NUMERIC_CHECK di json_encode karena akan secara otomatis memperbaikinya
Erick
-2

json_encode membuat serial beberapa struktur data dalam format JSON untuk dikirim melalui jaringan. Oleh karena itu semua konten akan menjadi tipe string. Sama seperti ketika Anda menerima beberapa parameter dari $ _POST atau $ _GET.

Jika Anda harus membuat operasi numerik pada nilai yang dikirim, cukup konversikan ke int terlebih dahulu (dengan fungsi intval () dalam PHP atau parseInt () dalam Javascript) dan kemudian jalankan operasi.

rogeriopvl
sumber
bukan itu yang dia bicarakan. dia berbicara tentang json yang memiliki tanda kutip ganda di sekitar angka.
JasonWoof
Dalam kasus JSON, itu menghemat Jenis. Bayangkan menulis Obyek JavaScript literal, setiap nilai yang dikutip menjadi string, tetapi angka yang tidak dikutip menjadi bilangan bulat, 0x [0-9a-z] menjadi hex dll. Ada perbedaan jenis dengan PHP, seperti, tidak ada yang namanya array asosiatif, hanya Objects atau diindeks array dll
bucabay
Baik. Masalah yang ia hadapi, adalah bahwa ia memiliki variabel php, yang menurutnya bertipe int, karena berasal dari kolom DB bertipe int. Tetapi sebenarnya variabel PHP memiliki tipe string, dengan demikian kutipan di JSON.
JasonWoof
-2

Baiklah, PHP json_encode () mengembalikan sebuah string.

Anda dapat menggunakan parseFloat () atau parseInt () dalam kode js:

parseFloat('122.5'); // returns 122.5
parseInt('22'); // returns 22
parseInt('22.5'); // returns 22
Richard Knop
sumber
Terima kasih. Saya berharap ada metode yang lebih elegan.
Chris Barnhill
1
ya, cara teraman adalah mengurai mereka. tapi sekali lagi, bukankah Javascript diketik secara longgar?
mauris
Hanya komentar: Ini diketik secara longgar, masih hasil dari "1" +1 akan menjadi ... 11 - jadi menggunakan JS Anda harus lebih perhatian daripada dalam bahasa jenis yang kuat, karena mereka akan memperingatkan Anda, JS hanya melakukan apa itu anggap yang terbaik jika menangani String-Numbers ...
SamiSalami
Ya tapi bukan itu intinya, json_encode seharusnya tidak menambahkan tanda kutip ke bidang angka.
andreszs
-3

Seperti kata oli_arborum, saya pikir Anda dapat menggunakan preg_replaceuntuk melakukan pekerjaan. Ubah saja perintah seperti ini:

$json = preg_replace('#:"(\d+)"#', ':$1', $json);
Santini Arnaud
sumber