PHP json_encode 인코딩 숫자를 문자열로


142

PHP json_encode 함수에 문제가 있습니다. 숫자를 문자열로 인코딩합니다. 예 :

array('id' => 3)

된다

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

js가이 값을 만나면이를 문자열로 해석하고 숫자 연산이 실패합니다. 누구든지 json_encode숫자를 문자열로 인코딩 하지 못하게하는 방법을 알고 있습니까? 감사합니다!


이것은 버전 별 문제라는 것이 밝혀졌습니다. 때때로 MySql 데이터베이스에서 가져 오면 올바른 유형이 유지됩니다. 이전 버전에서는 모든 것을 문자열로 반환 할 수 있습니다. 오늘 아침에 썼습니다 shakyshane.com/blog/output-json-from-php.html
shane

1
나는 같은 문제가 있었고 모델에서 Laravel의 뮤 테이터를 사용하여 내 문제를 해결할 수있었습니다. 모델의 값을 수정할 수 있습니다. laravel.com/docs/eloquent#accessors-and-mutators 처음에는 그것을 얻지 못했지만이 질문이 도움이되었습니다. stackoverflow.com/questions/16985656/…
Jazzy

답변:


28

나는 매우 빠른 테스트를 수행했습니다.

$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를 사용하고 있습니까? 아니면 테스트 사례가 게시 한 예보다 더 복잡합니까?

아마 http://bugs.php.net/의 하나의 버그 보고서 와 관련이있을 수 있습니까? 예를 들어, 버그 # 40503 : json_encode 정수 변환이 PHP와 일치하지 않습니까?


아마 버그 # 38680은 BTW, 당신도 관심을 수 있을까?


고마워 마틴 5.2.9를 사용하고 있습니다. 숫자 데이터가 db에서 문자열로 읽히는 지 궁금합니다. 필드 유형이 int라고 확신하지만 다른 설명은 생각할 수 없습니다. 시스템에서 빠른 테스트를 시도하고 동일한 결과가 나오는지 확인합니다.
Chris Barnhill

12
약 5.2.9; 데이터가 데이터베이스에서 오는 경우 문제가있을 수 있습니다. 데이터가 문자열로 캐스팅 된 모든 데이터를 데이터베이스에서 가져 오는 것을 종종 보았습니다 (PDO 및 mssql에서 이것을 보았습니다. 그러나 올바르게 기억하면이 또한 발생합니다) 새로운 mysqlnd 드라이버가 아직 존재하지 않는 PHP <5.3의 MySQL의 경우) ;;; 데이터의 모양을 확인하기 위해 var_dump를 사용하여 데이터의 각 부분 유형을 출력 할 수 있습니다.
Pascal MARTIN

(계속) 숫자 값의 데이터 유형이 문자열이라고 생각합니까? 어떤 아이디어?
Chris Barnhill

1
"MySQL에서 데이터가 문자열로 반환되는 이유"의 기술적 이유를 정확히 모른다; 아마도 PHP와 MySQL 사이의 드라이버와 관련이있을 것입니다; 그것은 PHP 5.3과 함께 제공되는 새로운 mysqlnd 드라이버에 의해 (적어도 경우에 따라) 수정되는 것입니다 ( blog.ulf-wendel.de/?p=184 참조 ; 페이지에서 "정수"를 검색하여 흥미로운 것을 찾으십시오. 문장) ;; 그러나 나는 이것이 좋지 않다는 것에 동의합니다 ^^
Pascal MARTIN

json_encode ()에 의해 반환 된 숫자 데이터가 따옴표로 묶여 있지 않아도 여전히 문자열입니다. json_encode () 함수의 리턴 값은 문자열입니다. MySQL이 모든 필드를 문자열로 반환하는 것과 관련하여 PDO 에서이 문제가 발생했습니다. 내가 보는 것처럼 항상 PHP에서 숫자 값을 정수 (또는 부동 소수점)로 변환하여 MySQL 또는 다른 데이터베이스가 올바른 유형의 값을 반환하지 않도록하십시오.
Richard Knop

352

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"}

4
JSON_NUMERIC_CHECK에는 PHP 5.3.3이 필요합니다.
Robert

10
IE에서 .toLowerCase ()를 폭파하여 숫자 레이블을 정수로 캐스팅 할 때까지 완벽하게 작동했습니다. 이 솔루션은 단순하지만 지나치게 조심하십시오.
Brad Koch

6
당신은 나의 영웅입니다.
Petrogad

5
문자열이 숫자가 아니라 다음과 같은 내용 인 경우 부작용이 있습니다 : 5252788e16597. 참조 : bugs.php.net/bug.php?id=64695
TonyQ

20
JSON_NUMERIC_CHECK문자열을 구문 분석하려고 시도하여 숫자인지 아닌지를 자동으로 추측합니다. 당신이 그것에 대해 생각하면 그것은 매우 신뢰할 수 없습니다. 모든 숫자 모양의 속성을 원하는 속성뿐만 아니라 숫자 로 변환 하고 숫자처럼 보이는 경우에만 수행합니다. 안전하지 않으면 최소한 흔들립니다. 생성 된 JSON을 소비하는 코드는 유형 중 하나에 의존 할 수 있습니다. 이러한 기대가 충족되지 않으면 이상한 일이 발생할 수 있습니다. 모범 사례와 안전에 관심이있는 경우 원하는 값을 선택적으로 변환해야합니다.
wadim

35

나도 마찬가지로 DB (PostgreSQL)에서 읽고 있었고 모든 것이 문자열이었습니다. 각 행을 반복하고 최종 결과 배열을 작성하기 위해 행을 수행하므로

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

루프 내에서 정수 값으로 강제합니다. 내가 할 때 json_encode($result_arr)지금, 그것은 정확하게 숫자로 포맷합니다. 이를 통해 데이터베이스에서 나오는 숫자와없는 숫자를 제어 할 수 있습니다.

편집하다:

json_encode()함수는 또한 JSON_NUMERIC_CHECK플래그를 두 번째 인수로 사용하여 즉시이를 수행 할 수 있습니다. 이 사용자 예제에 나와있는 문서 (아래에 복사 됨)에주의하여 사용해야합니다. 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전화 번호 및 기타 숫자 문자열 값도 변환 하므로주의하십시오. 이로 인해 선행 0 또는 '+'에 문제가 발생할 수 있습니다 ... DB 읽기 기능 에서이 문제를 해결하는 것이 좋습니다.
시저 솔


7

같은 문제가 발생합니다 (PHP-5.2.11 / Windows). 이 해결 방법을 사용하고 있습니다

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

따옴표로 묶인 모든 (음이 아닌 정수) 숫자를 숫자 자체로 바꿉니다 ( ' "42"'는 '42'가 됨).

PHP manual의이 주석 도 참조하십시오 .


코드에 감사하지만 슬프게도 객체 이름으로 숫자가 있기 때문에 json에서 작동하지 않았으며 json을 유효하지 않게 렌더링하는 것 같습니다 :(
SSH This

@SSH : 아마도이 구문을 사용하여 배열을 객체가 아닌 JSON 인코딩 배열로 변환해야합니다. $json_array = json_encode($some_array, false);따라서 잘못된 인수는 PHP가 객체 변환을하지 않도록 지시합니다.
hyde

이 해결 방법을 사용하는 것은 전혀 안전하지 않습니다. 당신은 같은 구조와 잘못된 JSON을 얻을 것이다 그 :json_encode(array(-1=>'que', '0'=>'-1'))
알렉스 Yaroshevich

다른 방법으로 문제가 있었는데 PHP 7.0에서 문자열로 인코딩 된 정수가 필요했고 이것을 사용했습니다.$this->data = preg_replace("/\" *?: *?(\d+)/", '":"$1"', $this->data);
Maciej Swic

소수점을 포함하기 위해 원래 정규 표현식을` "/\"(\d+\.?\d*)\"/"`로 변경합니다. 또 다른 메모는 JSON_NUMERIC_CHECK를 사용하는 사람들이 문자열이 올바른 경우 문제에 직면한다는 것입니다 과학적 표기법의 숫자. 예 : 19E008. JSON_NUMERIC_CHECK는 이것을 190000으로 변환합니다 ...
Sahib Khan

3

다음 테스트는 유형을 문자열로 변경하면 json_encode ()가 숫자를 JSON 문자열 (즉, 큰 따옴표로 묶음)로 반환하는지 확인합니다. settype (arr [ "var"], "정수") 또는 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>";

?>

2

완성도를 높이기 위해 (아직 설명을 추가 할 수 없으므로)이 세부 정보를 다른 답변으로 추가하겠습니다.

(편집 : 소스 데이터 (예 : OP의 경우 데이터베이스 결과 세트)가 문제가 될 수 있음을 인식 한 후 읽으십시오 (숫자 열을 문자열로 반환하여), 실제로 json_encode ()는 문제의 원인이 아닙니다)

" mysql_fetch_array " 의 매뉴얼 페이지 :

페치 된 행에 해당하는 문자열 배열을 리턴합니다 .

... 및 " mysql_ fetch_ row ":

페치 된 행에 해당하는 문자열 의 숫자 형 배열을 리턴합니다.

명확하게 말한다; 반환 된 배열의 항목은 문자열입니다.

(나는 phpBB2에서 DB 클래스를 사용하고 있었고 (예, 쓸모가 없습니다!) 해당 클래스의 "sql_fetchrow ()"메소드는 "mysql_fetch_array ()"를 사용합니다)

그것을 깨닫지 못하고 결국이 질문을 찾고 문제를 이해하게되었습니다! :)

파스칼 마틴 (Pascal Martin)은 그의 후속 의견에서 위에서 언급했듯이 소스에서 "잘못된 유형"문제를 처리하는 솔루션을 생각합니다 (예 : " mysql_field_type () "함수를 사용하고 가져 오기 직후 캐스팅을 수행하는 것으로 생각합니다. "object"?))와 같은 다른 페치 메소드가 일반적으로 더 좋습니다.


2

그래서 파스칼 마틴은 여기에 충분한 신용을 받고되지 않습니다. 모든 JSON 리턴에서 숫자 값을 확인하는 것은 수백 개의 서버 측 기능이있는 기존 프로젝트에는 적합하지 않습니다.

php-mysql을 php-mysqlnd로 바꾸었고 문제가 사라졌습니다. 숫자는 숫자, 문자열은 문자열, 부울은 부울입니다.


0

또한 데이터베이스에서 데이터를 처리하는 데 동일한 문제가 발생했습니다. 기본적으로 문제는 json으로 변환 할 배열의 유형이 PHP가 정수가 아닌 문자열로 인식한다는 것입니다. 필자의 경우 DB 열 계산 행에서 데이터를 반환하는 쿼리를 만들었습니다. PDO 드라이버는 열을 int가 아니라 문자열로 인식합니다. 영향을받는 열에서 int로 캐스트를 수행하여 해결했습니다.


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

0

그것은 PHP 버전 문제입니다, 같은 문제로 PHP 버전을 5.6으로 업그레이드하여 문제를 해결했습니다.


0

값을 int 또는 float로 캐스팅하면 문제가 해결됩니다. 예를 들면 다음과 같습니다.

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

0

문제가 발생하면 (int)를 사용할 수 있습니다 !! 잘 작동합니다.


-1

같은 문제가 발생하여 데이터베이스가 값을 문자열로 반환했습니다.

이 문제를 해결 방법으로 사용합니다.

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

값에 1을 곱하여 숫자로 변환합니다.

누군가를 돕는 희망


승수를 사용하는 것이 가장 효율적인 솔루션은 아닙니다. 자동으로 수정되므로 json_encode에서 JSON_NUMERIC_CHECK 사용을 고려하십시오
Erick

-2

json_encode는 일부 데이터 구조를 JSON 형식으로 직렬화하여 네트워크를 통해 전송합니다. 따라서 모든 내용은 문자열 유형입니다. $ _POST 또는 $ _GET에서 일부 매개 변수를받을 때와 같습니다.

전송 된 값에 대해 숫자 연산을해야하는 경우, 먼저 intval ( PHP 의 intval () 함수 또는 Javascript의 parseInt ()) 을 사용하여 값을 int로 변환 한 다음 조작을 실행하십시오.


그건 그가 말하는 것이 아닙니다. 그는 숫자 주위에 큰 따옴표가있는 json에 대해 이야기하고 있습니다.
JasonWoof

JSON의 경우 유형을 보존합니다. 리터럴 자바 스크립트 객체를 작성한다고 가정 해 봅시다. 따옴표로 묶은 값은 문자열이되고 따옴표로 묶지 않은 숫자는 정수가되고 0x [0-9a-z]는 16 진수가됩니다. PHP와 형식 차이는 다음과 같습니다. 연관 배열, 객체 또는 인덱싱 된 배열 등
bucabay

권리. 그가 가지고있는 문제는 PHP 변수가 있고 int 유형의 DB 열에서 왔기 때문에 int 유형을 가지고 있다고 생각했다는 것입니다. 그러나 실제로 PHP 변수에는 유형 문자열이 있으므로 JSON에 따옴표가 있습니다.
JasonWoof

-2

PHP json_encode ()는 문자열을 반환합니다.

js 코드에서 parseFloat () 또는 parseInt ()를 사용할 수 있습니다.

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

감사. 더 우아한 방법이 있기를 바랐습니다.
Chris Barnhill

1
그래, 가장 안전한 방법은 그것들을 파싱하는 것입니다. 그러나 다시 한 번 자바 스크립트를 느슨하게 입력하지 않습니까?
mauris

그냥 주석 : 그것은 느슨하게 입력되었지만 여전히 "1"+1의 결과는 ... 11입니다-JS를 사용하면 강력한 유형 언어보다주의를 기울여야합니다 .JS는 경고합니다. 생각입니다 최고의 가장 문자열 - 숫자를 처리하는 경우 ...
SamiSalami

예, 그러나 요점이 아닙니다. json_encode는 숫자 필드에 따옴표를 추가해서는 안됩니다.
andreszs

-3

oli_arborum이 말했듯 preg_replace이 작업을 수행하는 데 사용할 수 있다고 생각합니다 . 다음과 같이 명령을 변경하십시오.

$json = preg_replace('#:"(\d+)"#', ':$1', $json);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.