2011-01-11 3 views
31

json_encode()이 유효하지 않은 (UTF-8이 아닌) 문자를 포함하는 문자열에 대해 null을 반환하지 않게 할 방법이 있습니까?json_encode()가 잘못된 문자로 문자열을 삭제하는 것을 방지하는 방법

복잡한 시스템에서 디버깅하는 것이 엉망이 될 수 있습니다. 유효하지 않은 문자를 실제로 보거나 적어도 생략 한 것은 훨씬 더 적합 할 것입니다. 문자 그대로 json_encode()은 전체 문자열을 자동으로 삭제합니다.

예 (에서 UTF-8) :

[null,"Washington","Nairobi"] 

원하는 결과에

$string = 
    array(utf8_decode("Düsseldorf"), // Deliberately produce broken string 
     "Washington", 
     "Nairobi"); 

print_r(json_encode($string)); 

결과 :

["D�sseldorf","Washington","Nairobi"] 

: 나는하지만들기 위해 찾고 있어요 깨진 문자열은 json_encode()에서 작동합니다. 나는 인코딩 오류를 쉽게 진단 할 수있는 방법을 찾고있다. A null 문자열은 유용하지 않습니다.

+0

''Düsseldorf ''문자열은'utf8_decode()'할 때만 유효하지 않습니까? –

+0

@Matt no는 응답자가 테스트 할 깨진 문자열을 만드는 예제 일뿐입니다. –

+0

그래서 잘못된 UTF-8 문자열을 포함 할 수있는 JSON 데이터가 있습니까? – Gumbo

답변

39

php는 오류가 발생하지만 은 display_errors를으로 설정하지 않은 경우에만 발생합니다. display_errors 설정은 오류가 트리거되는지 여부가 아닌 표준 출력에 오류를 인쇄할지 여부를 제어하기 때문에 설정해야합니다. 나는 당신이 display_errors을 가지고있을 때 다른 모든 PHP 오류를 볼 수 있다고하더라도 PHP는 단지 이 오류를 숨기지 않고을 실행하지 않는다고 강조하고 싶습니다. 즉, 오류 로그에 표시되지 않으며 사용자 정의 error_handlers가 호출되지 않습니다. 오류는 절대로 발생하지 않습니다.

다음은이 방법을 보여줍니다 일부 코드입니다 :

error_reporting(-1);//report all errors 
$invalid_utf8_char = chr(193); 

ini_set('display_errors', 1);//display errors to standard output 
var_dump(json_encode($invalid_utf8_char)); 
var_dump(error_get_last());//nothing 

ini_set('display_errors', 0);//do not display errors to standard output 
var_dump(json_encode($invalid_utf8_char)); 
var_dump(error_get_last());// json_encode(): Invalid UTF-8 sequence in argument 

기괴한과 불행한 행동이이 버그 https://bugs.php.net/bug.php?id=47494과 몇 가지 다른 관련되어 있는지, 그리고 지금까지 해결 될 것 같지 않습니다.

해결 방법 :

실행 가능한 해결책이 될 수 있습니다로 json_encode에 전달하기 전에 문자열을 청소합니다.

$stripped_of_invalid_utf8_chars_string = iconv('UTF-8', 'UTF-8//IGNORE', $orig_string); 
if ($stripped_of_invalid_utf8_chars_string !== $orig_string) { 
    // one or more chars were invalid, and so they were stripped out. 
    // if you need to know where in the string the first stripped character was, 
    // then see http://stackoverflow.com/questions/7475437/find-first-character-that-is-different-between-two-strings 
} 
$json = json_encode($stripped_of_invalid_utf8_chars_string); 

http://php.net/manual/en/function.iconv.php

설명서는

//IGNORE이 자동으로 대상 캐릭터 세트로 불법 문자를 삭제했다.

그래서 문제가되는 문자를 먼저 제거하면 이론적으로 json_encode()가 질식하고 실패 할 것이라는 것을 알 수 있습니다. //IGNORE 플래그가있는 iconv의 출력이 유효한 utf8 문자의 json_encodes 개념과 완벽하게 호환되는지 확인하지 않았으므로 구매자가주의해야합니다. 아직 실패하는 경우가 있으므로주의해야합니다. 캐릭터 세트 문제는 싫어.

+0

재미 있고 이상하게 들린다! 나는 내일 이것을 들여다 볼 것이다. 경고는 나를 위해 충분할 것입니다 –

+0

iconv() 아이디어는 음모를 꾸미고 다만 작동 할지도 모릅니다. 나는 내일도 그걸 시도 할 것이다. –

+0

이것은 나를 위해 일했습니다. json_encoding 전에 데이터를'iconv() '하고있다. –

3

당신이 다루는 모든 문자열의 인코딩을 알아야하거나 고통의 세계에 들어서 야합니다.

UTF-8은 사용하기 쉬운 인코딩입니다. 또한 JSON은 UTF-8 (http://www.json.org/JSONRequest.html)을 사용하도록 정의되었습니다. 그럼 왜 그것을 사용하지?

짧은 대답 : json_encode()가 문자열을 삭제하는 것을 피하는 방법은 유효한 UTF-8인지 확인하는 것입니다.

+0

그래, 나는 그 사실을 알고있다. 앞에서 말한 것처럼 갑자기 깨진 수신 인코딩을 디버그하는 것은 엄청나게 어려워졌습니다. JSON의 일부가 깨져 보지 않고 사라지는 것입니다. 이것은 깨진 인코딩 자체를 우회하는 것보다 더 쉽게 오류를 발견하는 것입니다. –

+0

json_decode()를 각 문자열의 인코딩을 테스트하거나 무언가가 유효한 UTF-8이 아닐 때 실제로 볼 수있는 곳으로 대체하거나 대체하십시오. ? – metamatt

5
$s = iconv('UTF-8', 'UTF-8//IGNORE', $s); 

이 문제가 해결되었습니다. PHP에서 사람들이 왜 json_encode()을 고쳐서 더 쉽게 삶을 만들지 못했는지 잘 모르겠습니다.

어쨌든 json_encode()는 데이터에 특수 문자 (예 : 스웨덴 문자)가 포함되어 있어도 객체를 만들 수 있습니다. 그러면 (escape(), unescape(), encodeURIComponent(), decodeURIComponent() 함께) 원래의 부호화 데이터를 다시 디코딩 할 필요없이 자바 스크립트 결과를 사용할 수

;

나는 (유식) PHP에서 이런 식으로 사용하고 있습니다 :

$template = iconv('UTF-8', 'UTF-8//IGNORE', $screen->fetch("my_template.tpl")); 


가 그럼 난 자바 스크립트로 결과를 전송하고 내 문서에 바로 innerHTML 준비 템플릿 (HTML 평화)하고있다.

간단히 말해 위의 행은 어떤 인코딩과도 작동하도록하기 위해 어떻게 든 json_encode()에 구현되어야합니다.

+1

이 한 줄로 내 문제가 해결되었습니다. 감사합니다 –

1

대신의 iconv 기능을 사용하여, 당신은 direclty 당신이 당신의 PHP 파일의 헤더에 "문자셋 = UTF-8"을 넣어 있는지 확인

JSON_UNESCAPED_UNICODE 옵션으로로 json_encode (> = PHP5.4.0)를 사용할 수 있습니다 :

header ('Content-Type : application/json; charset = utf-8');

+0

어떻게 이것이 도움이 될지 모르겠다 - 모든'JSON_UNESCAPED_UNICODE'는 유니 코드 문자를'\ uxxxx' 엔티티로 변환하지 않을 것입니다. 유효하지 않은 문자가있을 때 빈 문자열이 나오지는 않습니다. –

+0

이것은 나를 위해 훌륭했습니다! 다른 스레드에서 비슷한 제안을 보았지만 헤더를 추가해야한다는 사실을 알지 못했습니다. 감사합니다! – Wingman1487

4

이 함수는 문자열에서 유효하지 않은 모든 UTF8의 문자를 제거합니다 :

function removeInvalidChars($text) { 
    $regex = '/([\x00-\x7F] | [\xC0-\xDF][\x80-\xBF] | [\xE0-\xEF][\x80-\xBF]{2} | [\xF0-\xF7][\x80-\xBF]{3}) | ./x'; 
    return preg_replace($regex, '$1', $text); 
} 

내가 그것을 사용 JSON에 엑셀 문서를 변환 한 후, 엑셀 문서가 UTF8에서 보장하지 않는 한.

잘못된 문자를 보이는 문자로 변환하는 것이 특히 현명한 방법이라고 생각하지 않습니다. 잘못된 문자를 유니 코드 replacement character 인 U + FFFD로 바꿀 수는 있지만 위의 정규식을 사용하면 잘못된 문자를 삭제하는 것보다 나은 사용자 환경을 제공하지 못합니다.

관련 문제