Dizeler olarak PHP json_encode kodlama numaraları


142

PHP json_encode işlevi ile bir sorun yaşıyorum. Sayıları dize olarak kodlar, örn.

array('id' => 3)

olur

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

Js bu değerlerle karşılaştığında bunları dizeler olarak yorumlar ve sayısal işlemler başarısız olur. json_encodeSayıları dize olarak kodlamaktan kaçınmanın bir yolunu bilen var mı ? Teşekkür ederim!


Bunun sürüme özgü bir sorun olduğu ortaya çıkıyor. Bazen bir MySql veritabanından bir çekme doğru türleri korur. Eski sürümlerde, her şeyi bir dize olarak döndürebilir. Bu sabah bunun hakkında yazdım. shakyshane.com/blog/output-json-from-php.html
shane

1
Aynı sorunu yaşıyordum ve Laravel'in Modeldeki Mutatörlerini kullanarak benimkini çözebildim. Modeldeki değerleri değiştirmenizi sağlar. laravel.com/docs/eloquent#accessors-and-mutators İlk başta tam olarak anlamadım, ancak bu soru yardımcı oldu: stackoverflow.com/questions/16985656/…
Jazzy

Yanıtlar:


28

Çok hızlı bir test yaptım:

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

Yanılmıyorsam, bu tarif ettiğiniz gibi görünüyor?

Ve çıktı olarak alıyorum:

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

Bu nedenle, bu durumda tamsayılar dizeye dönüştürülmemiştir.


Yine de, bu, kullandığımız PHP sürümüne bağlı olabilir: PHP sürümüne bağlı olarak, düzeltilen birkaç json_encode ile ilgili hata var ...

Bu test PHP 5.2.6 ile yapılmıştır; PHP 5.2.9 ve 5.3.0 ile aynı şeyi alıyorum; Yine de test etmek için başka bir 5.2.x sürümüm yok :-(

Hangi PHP sürümünü kullanıyorsunuz? Yoksa test durumunuz, yayınladığınız örnekten daha mı karmaşık?

Belki de http://bugs.php.net/ ile ilgili bir hata raporu ilgili olabilir? Örneğin, Hata # 40503: json_encode tamsayı dönüştürme PHP ile tutarsız mı?


Belki de Hata # 38680 ilginizi çekebilir , btw?


Teşekkürler Martin. 5.2.9 kullanıyorum. Sayısal veri db dize olarak okunuyor olup olmadığını merak ediyorum? Alan türlerinin int olduğundan eminim, ancak başka bir açıklama düşünemiyorum. Hızlı testinizi sistemimde deneyeceğim ve aynı sonucu alıp almadığımı göreceğim.
Chris Barnhill

12
5.2.9 hakkında OK; verileriniz bir veritabanından geliyorsa, sorun orada olabilir: Sık sık veri dizesinden dökülen her şeyi ile veritabanından geldiğini gördüm (PDO ve mssql ile gördüm; ama, doğru hatırlıyorsam, bu da olur PHP için MySQL için <5.3, yeni mysqlnd sürücüsü henüz mevcut olmadığında) ;; verilerinizin nasıl göründüğünü kontrol etmek için, verilerin her bölümünün türlerini çıktı alan var_dump kullanabilirsiniz.
Pascal MARTIN

(devam) sayısal değerler için veri türünün dize olduğunu düşünüyor? Herhangi bir fikir?
Chris Barnhill

1
Ben "veri neden bir dize olarak MySQL döndürülür" teknik nedeni tam olarak bilmiyorum ;; muhtemelen PHP ve MySQL arasındaki sürücü ile ilgili bir şey ;; PHP 5.3 ile gelen yeni mysqlnd sürücüsü tarafından düzeltilen (en azından bazı durumlarda) bir şeydir (bkz. blog.ulf-wendel.de/?p=184 ; ilginç olanı bulmak için sayfada "integer" araması yapın cümle) ;; ama bunun hoş olmadığını kabul ediyorum ^^
Pascal MARTIN

Json_encode () tarafından döndürülen sayısal verilerin tırnak içinde olmaması önemli değildir, yine de bir dizedir. Json_encode () işlevinin dönüş değeri bir dizedir. Tüm alanları dize olarak dönen MySQL ile ilgili olarak, evet ben de özellikle PDO ile karşılaştım. Gördüğüm şekilde her zaman PHP'de tamsayı (veya float) için sayısal olmasını beklediğiniz değerleri almanız gerekir, doğru türdeki değerleri döndürmek için MySQL veya başka bir veritabanına güvenmeyin.
Richard Knop

352

PHP 5.3.3'ten bu yana, sayıları otomatik olarak dönüştürmek için bir bayrak bulunduğunu unutmayın (PHP 5.3.0'da options parametresi eklendi):

$arr = array( 'row_id' => '1', 'name' => 'George' );
echo json_encode( $arr, JSON_NUMERIC_CHECK ); // {"row_id":1,"name":"George"}

4
JSON_NUMERIC_CHECK PHP 5.3.3 gerektirir.
Robert

10
IE'de .toLowerCase () havaya uçurmak için sayısal bir tamsayıya kadar mükemmel çalıştı. Dikkatli olun, bu çözüm basit ama aşırı heveslidir.
Brad Koch

6
Sen benim kahramanımsın.
Petrogad

5
Dizeniz bir sayı değil, bunun gibi bir içerikse bazı yan etkileri vardır: 5252788e16597. başvuru: bugs.php.net/bug.php?id=64695
TonyQ

20
JSON_NUMERIC_CHECKbir dizenin sayı olup olmadığını otomatik olarak tahmin etmeye çalışır. Eğer düşünürseniz bu oldukça güvenilmez. Tüm sayısal görünümlü özellikleri sayılara dönüştürür (yalnızca istediğiniz özelliklere değil) ve bunu yalnızca sayıya benziyorsa yapar. Güvensiz değilse en azından titrek. Üretilen JSON'u tüketen kod, biri veya diğeri türüne bağlı olabilir. Bu beklentiler karşılanmazsa garip şeyler olabilir. İyi uygulamalara ve güvenliğe önem veriyorsanız, istediğiniz değerleri seçerek dönüştürmelisiniz.
wadim

35

Ben, aynı şekilde bir DB (PostgreSQL) okuma ve her şey bir dize oldu. Her satırın üzerinden geçeriz ve nihai sonuç dizimizi oluşturmak için onunla bir şeyler yaparız, bu yüzden

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

bir tamsayı değeri olmaya zorlamak için döngü içinde. json_encode($result_arr)Şimdi yaptığımda bunu doğru bir sayı olarak biçimlendiriyor. Bu, veritabanınızdan gelen bir sayı olup olmadığını kontrol etmenizi sağlar.

DÜZENLE:

json_encode()Fonksiyon aynı zamanda kullanılarak anında bunu yeteneğine sahiptir JSON_NUMERIC_CHECKkendisine ikinci bir argüman olarak bayrak. Belgede (aşağıda kopyalanan) bu kullanıcı örneğinde gösterildiği gibi kullanmaya dikkat etmelisiniz: http://uk3.php.net/manual/en/function.json-encode.php#106641

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

Ve sonra bu JSON'u alırsınız:

{"phone_number":33123456789}

Evet, sorun veri türlerini yorumlamayan DB adaptöründe, json_encodefonksiyonun DEĞİLDİR . Bu en doğru cevaptır, ancak JSON_NUMERIC_CHECKtelefon numaralarını ve diğer sayısal dize değerlerini de dönüştürdüğü için dikkatli olun ve bu, baştaki sıfırlarda veya '+' sorunlarına neden olabilir ... DB okuma işlevinde bu sorunu düzeltmenizi öneririz.
caesarsol


7

Aynı sorunla karşılaşıyorum (PHP-5.2.11 / Windows). Bu geçici çözümü kullanıyorum

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

tırnak işaretleri içine alınan tüm (negatif olmayan, tamsayı) sayıları, sayının kendisiyle değiştirir ('"42"', "42" olur).

PHP kılavuzundaki bu yoruma da bakınız .


Kod için teşekkürler, ama ne yazık ki benim nesne üzerinde bir sayı var çünkü benim json üzerinde işe yaramadı ve json geçersiz kılıyor gibi görünüyor :(
SSH Bu

@SSHBu, diziyi bir nesneye değil JSON kodlu bir diziye dönüştürmek için bu sözdizimini kullanmalısınız. $json_array = json_encode($some_array, false);Yani yanlış argüman PHP'ye nesne dönüşümü yapmamasını söyler.
hyde

Bu geçici çözümü kullanmak hiç güvenli değil. Bunun gibi yapılarla geçersiz json alırsınız:json_encode(array(-1=>'que', '0'=>'-1'))
Alex Yaroshevich

Ben başka bir şekilde bir sorun vardı, ben PHP 7.0 dizeleri olarak kodlanmış benim tam sayıları gerekli ve bunu kullanılır$this->data = preg_replace("/\" *?: *?(\d+)/", '":"$1"', $this->data);
Maciej Swic

Ondalık sayıları dahil etmek için orijinal normal ifadeyi `` /\"(\d+\.?\d*)\"/ "` olarak değiştireceğim, başka bir not da JSON_NUMERIC_CHECK kullanan çocuklar bir dize de doğru olduğunda sorunla karşılaşacak bilimsel gösterimde sayı. örneğin, 19E008. JSON_NUMERIC_CHECK bunu 190000'e dönüştürecek ...
Sahib Khan

3

Aşağıdaki sınama, türün dizeye değiştirilmesinin json_encode () işlevinin sayısal olarak JSON dizesi olarak döndürülmesine neden olduğunu doğrular (örneğin, çift tırnak işaretleri içine alınır). Düzeltmek için settype (arr ["var"], "integer") veya settype ($ arr ["var"], "float") kullanın.

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

?>

2

Tamlık uğruna (henüz yorum ekleyemediğim için) bu ayrıntıyı başka bir cevap olarak da ekleyeyim:

(Düzenle: Kaynak verilerin (yani OP'nin durumunda, veritabanı sonuç kümesinin) sorun olabileceğini (sayısal sütunları dizeler olarak döndürerek) ve aslında json_encode () sorunun kaynağı olmadığını fark ettikten sonra okunacak)

Her iki " mysql_fetch_array " kılavuz sayfaları :

Alınan satıra karşılık gelen bir dizgi dizisi döndürür ,

... ve " mysql_ fetch_ row ":

Alınan satıra karşılık gelen sayısal bir dizgi dizisi döndürür

açıkça belirtiyor; döndürülen dizideki girdiler dize olur.

(Ben phpBB2 DB sınıfını kullanıyordum (evet biliyorum, eski!) Ve bu sınıfın "sql_fetchrow ()" yöntemi "mysql_fetch_array ()" kullanır)

Bunun farkında değilim, aynı zamanda bu soruyu buldum ve sorunu anladım! :)

Pascal Martin'in yukarıdaki yorumlarında belirttiği gibi, kaynaktaki "yanlış tür" sorununa dikkat eden bir çözüm olduğuna inanıyorum (yani " mysql_field_type () " işlevini kullanarak ve getirme işleminden hemen sonra döküm yaparak (veya "nesne"?) gibi diğer getirme yöntemleri genel olarak daha iyi olur.


2

Yani Pascal MARTIN burada yeterince kredi alamıyor. Her JSON dönüşünde sayısal değerlerin kontrol edilmesi, yüzlerce sunucu tarafı işlevine sahip mevcut bir proje için mümkün değildir.

Ben php-mysql yerine php-mysqlnd, ve sorun gitti. Sayılar sayı, dize katar, boolean boolean.


0

Veritabanından veri işlerken de aynı sorunu yaşadım. Temelde sorun, json'da dönüştürülecek dizideki türün PHP tarafından tamsayı değil bir dize olarak tanınmasıdır. Benim durumumda bir DB sütun sayma satırından veri döndüren bir sorgu yaptı. PDO sürücüsü, sütunu int olarak değil, dizeler olarak tanır. Etkilenen sütunda int olarak bir kadro yaparak çözdüm.


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

0

bu php sürümü sorun, aynı sorunu php sürüm 5.6 yükseltti sorunu çözdü


0

Değerleri bir int veya float'a dökmek bunu düzeltiyor gibi görünüyor. Örneğin:

$coordinates => array( 
    (float) $ap->latitude,
    (float) $ap->longitude 
);

0

Herhangi bir sorun oluşursa (int) kullanabilirsiniz !! İyi çalışacaktır.


-1

Sadece aynı soruna koşmak ve değerleri dizeleri olarak dönen veritabanı oldu.

Bunu geçici bir çözüm olarak kullanıyorum:

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

Bu, bir sayıya dönüştürmek için değeri 1 ile çarpmaktır

Birisine yardımcı olan umarım


çarpan kullanmak en etkili çözüm değildir. otomatik olarak düzelteceğinden JSson_NUMERIC_CHECK kullanmayı düşünün
Erick

-2

json_encode, ağ üzerinden gönderilecek bazı veri yapısını JSON biçiminde serileştirir. Bu nedenle, tüm içerik dizgide olacaktır. Tıpkı $ _POST veya $ _GET'den bir parametre aldığınızda olduğu gibi.

Gönderilen değerler üzerinde sayısal işlemler yapmanız gerekiyorsa, bunları önce int'e dönüştürün ( PHP'de intval () işleviyle veya Javascript'te parseInt () ile ) ve sonra işlemleri yürütün.


bahsettiği şey bu değil. sayılar etrafında çift tırnak bulunan json hakkında konuşuyor.
JasonWoof

JSON durumunda, Türleri korur. Değişmez bir JavaScript Nesnesi yazdığınızı düşünün, alıntılanan değerler dize olur, ancak alıntılanmamış sayılar tamsayı haline gelir, 0x [0-9a-z] hex vb. Olur. PHP ile tür farklılıkları vardır, örneğin, İlişkilendirilebilir bir dizi, yalnızca Nesneler veya dizine
alınmış

sağ. Sahip olduğu sorun, int tipi olduğunu düşündüğü bir php değişkenine sahip olmasıydı, çünkü int tipi bir DB sütunundan geldi. Ama aslında PHP değişkeni tip dizgisine sahipti, bu yüzden JSON'daki tırnak işaretleri.
JasonWoof

-2

PHP json_encode () bir dize döndürür.

Js kodunda parseFloat () veya parseInt () yöntemini kullanabilirsiniz:

parseFloat('122.5'); // returns 122.5
parseInt('22'); // returns 22
parseInt('22.5'); // returns 22

Teşekkürler. Daha zarif bir yöntem olmasını umuyordum.
Chris Barnhill

1
evet, en güvenli yol onları ayrıştırmaktır. ama yine, Javascript gevşek yazılmamış mı?
mauris

Sadece bir yorum: Gevşek bir şekilde yazılmıştır, hala "1" + 1'in sonucu olacak ... Dize-Sayıları
işliyorsa

Evet ama önemli değil, json_encode sayısal alanlara tırnak eklememelidir.
andreszs

-3

Oli_arborum'un dediği gibi, preg_replaceiş yapmak için bir kullanabilirsiniz . Sadece komutu şu şekilde değiştirin:

$json = preg_replace('#:"(\d+)"#', ':$1', $json);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.