json_encode가 빈 문자열을 반환하는 이유


107

3 개의 중첩 배열이있는 간단한 PHP 구조가 있습니다.

나는 특정 객체를 사용하지 않고 2 개의 중첩 루프가있는 배열을 직접 만듭니다.

다음은 Json으로 변환하려는 배열의 var_dump 샘플입니다.

array (size=2)
  'tram B' => 
    array (size=2)
      0 => 
        array (size=3)
          'name' => string 'Ile Verte' (length=9)
          'distance' => int 298
          'stationID' => int 762
      1 => 
        array (size=3)
          'name' => string 'La Tronche Hôpital' (length=18)
          'distance' => int 425
          'stationID' => int 771
  16 => 
    array (size=4)
      0 => 
        array (size=3)
          'name' => string 'Bastille' (length=8)
          'distance' => int 531
          'stationID' => int 397
      1 => 
        array (size=3)
          'name' => string 'Xavier Jouvin' (length=13)
          'distance' => int 589
          'stationID' => int 438

다른 스크립트에서 나는 비슷한 구조를 가지고 있으며 json_encode잘 작동합니다. 그래서 이유를 이해하지 못합니다json_encode 여기서 작동 .

편집 : 인코딩에 문제가있는 것 같습니다. 때 mb_detect_encoding반환 ASCII의json_encode 작품 만이 UTF8을 반환 할 때, 그것은 더 이상 작동하지 않습니다.

Edit2 : 다음 을 의미하는 json_last_error()반환 JSON_ERROR_UTF8: 잘못된 UTF-8 문자, 잘못 인코딩되었을 수 있습니다 .


PHP 매뉴얼은 This function only works with UTF-8 encoded data.인코딩에 문제가 없어야 한다고 말합니다 .
MahanGM

13
문자열을에 전달하기 전에 배열 필드 에서 사용 utf8_encode()하십시오 . namejson_encode()
MahanGM

고마워 ! 나는 내 문제를 해결 한이 솔루션에 방금 나섰다.
Matthieu Riegler 2013 년

네, 답을 봤어요. 행운을 빕니다.
MahanGM

3
JSON_PARTIAL_OUTPUT_ON_ERROR옵션 을 사용 하여 문제를 확인합니다 (예 : UTF8이있는 필드는 null이 됨).
Peter Krauss

답변:


255

파기 2 시간 후 (편집 참조)

다음을 발견했습니다.

  • 제 경우에는 인코딩 문제입니다.
  • mb_detect_encoding 아마도 잘못된 응답을 반환합니다. 일부 문자열은 아마도 UTF-8이 아닐 것입니다.
  • 사용 utf8_encode()하는 문자열에 내 문제를 해결하지만, 아래 참고 참조

다음은 배열에 포함 된 모든 문자열을 UTF-8로 강제 변환 할 수있는 재귀 함수입니다.

function utf8ize($d) {
    if (is_array($d)) {
        foreach ($d as $k => $v) {
            $d[$k] = utf8ize($v);
        }
    } else if (is_string ($d)) {
        return utf8_encode($d);
    }
    return $d;
}

다음과 같이 간단히 사용하십시오.

echo json_encode(utf8ize($data));

참고 : utf8_encode () 는 문서에 따라 ISO-8859-1 문자열을 UTF-8로 인코딩하므로 입력 인코딩이 확실하지 않은 경우 iconv () 또는 mb_convert_encoding () 이 주석 및 기타 솔루션에 명시된대로 더 나은 옵션이 될 수 있습니다.


4
솔루션 ... 그러나, 한쪽 노트 주셔서 감사합니다 : 변경 } else {} else if (is_string ($d)) {; 그렇지 않으면 당신은 (예를 들어 문자열에 이르기까지 모든 변경됩니다 INT될 것이다 STRING).
Paul Peelen 2014-06-05

3
당신은 내 생명을 구했습니다. 이 기능을 찾을 때까지 모든 것을 끝내려고했습니다 !! 감사합니다.
silversunhunter 2015

2
WTF! 솔루션을 공유해 주셔서 감사합니다. 이 문제를 파악하는 데 많은 노력이 필요하다는 것을 알 수 있으며 그렇게하여 공유해 주셔서 감사합니다.
kris

1
3 일 동안 디버깅 한 후 지금 바로 키스 할 수 있습니다.
AJB

2
데이터베이스에서 읽는 경우 $ conn-> set_charset ( "utf8");
Andrew Briggs

36

Matthieu Riegler는 정말 좋은 솔루션을 제시했지만 객체를 처리하기 위해 약간 수정해야했습니다.

function utf8ize($d) {
    if (is_array($d)) 
        foreach ($d as $k => $v) 
            $d[$k] = utf8ize($v);

     else if(is_object($d))
        foreach ($d as $k => $v) 
            $d->$k = utf8ize($v);

     else 
        return utf8_encode($d);

    return $d;
}

참고 : json_last_error () 는 json_encode () / json_encode () 함수를 디버깅하는 데 도움이 될 수 있습니다.


elseif대신 해야하지 else if않습니까? (즉, 공백 없음).
Uwe Keim 16.

2
@UweKeim PHP 문서 "elseif 및 그렇지 않으면 중괄호를 사용할 때만 정확히 동일하게 간주됩니다"에 따르면 콜론 표기법을 사용하지 않는 한 동등 함을 의미합니다. 예if(): elseif:
Adam Bubela

1
잘 했어. PHP는 쓰레기이며 당신과 같은 사람들은 덤프에 가지 못하게합니다.
Lonnie Best

다음 else if(is_int($d)||is_bool($d)) return $d;과 같은 이유로 마지막 다른 것 앞에 a 를 삽입해야합니다 .{"success":true, "message":"Ⲃⲟⲟ𝓵ⲉⲁⲛ ⲁⲛⲇ Ⲓⲛϯⲉ𝓰ⲉꞅ𝛓"}
David Refoua

@ matthieu-riegler에게 @ paul-peelen이 추천 한 것처럼 : 마지막 else을 변경하십시오 else if(is_string ($d)). 그렇지 않으면 당신은 (예를 들어 문자열에 이르기까지 모든 변경됩니다 INT될 것이다 STRING).
Bruno Serrano

30

저에게이 문제에 대한 답은 charset=utf8PDO 연결 설정이었습니다 .

$dbo = new PDO('mysql:host=localhost;dbname=yourdb;charset=utf8', $username, $password);

2
또는 mysqli 함수에서 : mysqli_set_charset ($ connection, "utf8");
user18099

이것은 내 솔루션에 대한 힌트였습니다. msqli 연결의 원인이 거의 다릅니다. $mysqli->set_charset("utf8");데이터베이스 처리를 한 후에 전화 하십시오.
MaggusK

utf8mb4최신 MySQL 버전에서 사용하십시오 . utf8구식입니다.
Dharman

10

Adam Bubela는 내 문제를 해결하는 데 도움이 된 정말 좋은 솔루션을 제시했으며 여기에 단순화 된 기능이 있습니다.

function utf8ize($d)
{ 
    if (is_array($d) || is_object($d))
        foreach ($d as &$v) $v = utf8ize($v);
    else
        return utf8_encode($d);

    return $d;
}

1
나는 키를 보존하기 때문에 이것을 좋아합니다.
dev0

7

PHP 5.6에서 똑같은 문제가 있습니다. 내가 사용하는 서버 열기 UTF-8로 설정되어 Windows 7의 모든 캐릭터 세트에 + Nginx에 있습니다. 이론적 으로 공식 문서 에 따르면 플래그

JSON_UNESCAPED_UNICODE

이 문제를 해결해야합니다. 불행히도 이것은 내 경우가 아닙니다. 이유는 모르겠습니다. 위의 모든 스 니펫은 내 문제를 해결하지 못하므로 내 구현을 찾았습니다. 누군가를 도울 수 있다고 믿습니다. 적어도 러시아 문자는 테스트를 통과합니다.

function utf8ize($d) {
    if (is_array($d) || is_object($d)) {
        foreach ($d as &$v) $v = utf8ize($v);
    } else {
        $enc   = mb_detect_encoding($d);

        $value = iconv($enc, 'UTF-8', $d);
        return $value;
    }

    return $d;
}

4

이 대답은 작동합니다. 그러나 MySQL에서 데이터를 얻는 경우 (내가 그랬던 것처럼) 더 쉬운 방법이 있습니다.

데이터베이스를 열면 쿼리하기 전에 다음과 같이 mysqli를 사용하여 문자 집합을 설정할 수 있습니다.

/* change character set to utf8 | Procedural*/
if (!mysqli_set_charset($link, "utf8")) {
    printf("Error loading character set utf8: %s\n", mysqli_error($link));
    exit();
}

또는

/* change character set to utf8 | Object Oriented*/
if (!$mysqli->set_charset("utf8")) {
        printf("Error loading character set utf8: %s\n", $mysqli->error);
        exit();
 }

링크 : http://php.net/manual/en/mysqli.set-charset.php


4

이전 버전의 PHP (5.2)를 실행하는 서버에서이 문제가 발생했습니다. JSON_FORCE_OBJECT 플래그를 사용하고 있었는데 5.3까지 지원되지 않는 것 같습니다.

따라서 해당 플래그를 사용하는 경우 버전을 확인하십시오!

해결 방법은 다음과 같이 인코딩하기 전에 객체로 캐스팅하는 것 같습니다.

json_encode((object)$myvar);

3

반품 mb_detect_encoding이 정확하지 않을 수 있습니다.

$data = iconv('UTF-8', 'ISO-8859-1', 'La Tronche Hôpital');
var_dump(
    mb_detect_encoding($data),
    mb_detect_encoding($data, array('ISO-8859-1', 'UTF-8'))
);

기본 감지 순서에 따라 위의 결과가 다른 결과를 반환 할 수 있으므로 인코딩이 UTF-8로 잘못보고됩니다. ( 여기에 더 큰 예가 있습니다. 있습니다.)

데이터가 UTF-8로 인코딩되지 않았을 가능성 json_encode이 있으므로을 반환 false합니다. JSON 인코딩 전에 문자열을 UTF-8로 변환해야합니다.

$fromEncoding = 'ISO-8859-1'; // This depends on the data

array_walk_recursive($array, function (&$value, $key, $fromEncoding) {
    if (is_string($value)) {
        $value = iconv($fromEncoding, 'UTF-8', $value);
    }
}, $fromEncoding);

3

나는 ob_get_clean ()에서 데이터를 얻었고 같은 문제가 있었지만 위의 솔루션은 나를 위해 작동하지 않습니다. 제 경우 해결책은 이것이 누군가에게 도움이 될 것입니다.

$var = mb_convert_encoding($var, 'UTF-8');

2

그 문자열에 utf8_encode ()를 사용하면 내 문제가 해결되었습니다.


1

Adam Bubela의 답변을 개선했습니다. 블록이 {및}에 의해 닫히지 않는 것이 싫어요. 깨끗하고 버그를 소개하지 않거나 과거에 Perl을 사용했을 수도 있습니다. :)

<?php

class App_Updater_String_Util {    
    /**
     * Usage: App_Updater_String_Util::utf8_encode( $data );
     *
     * @param mixed $d
     * @return mixed
     * @see http://stackoverflow.com/questions/19361282/why-would-json-encode-returns-an-empty-string
     */
    public static function utf8_encode($d) {
        if (is_array($d)) {
            foreach ($d as $k => $v) {
                $d[$k] = self::utf8_encode($v);
            }
        } elseif (is_object($d)) {
            foreach ($d as $k => $v) {
                $d->$k = self::utf8_encode($v);
            }
        } elseif (is_scalar($d)) {
            $d = utf8_encode($d);
        }

        return $d;
    }
}

?>

0

이 데이터를 데이터베이스에서 mysqli_set_charset($connection, "utf8");가져 오면 데이터베이스에서 매개 변수를 가져올 때 연결 에서 사용 하십시오.


0

이 문제는 때때로 발생합니다-헤더 액세스 제어를 전달하지 않습니다.

제 경우에는 json_encode 전에 에코를 추가했다면. 그렇지 않으면 빈 페이지가 표시되었습니다.

나는 추가했다

header('Access-Control-Allow-Origin: *'); 

내 문제가 해결되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.