json_encode()가 잘못된 문자를 가진 문자열을 삭제하지 않도록 하는 방법
json_encode()null비활성(UTF-8 이외) 문자를 포함하는 문자열에 대해 어떻게 생각하십니까?
복잡한 시스템에서 디버깅하는 것은 골칫거리일 수 있습니다.잘못된 문자를 실제로 보거나 최소한 생략하는 것이 훨씬 더 적합할 것입니다.json_encode()문자열 전체가 자동으로 드롭됩니다.
예(UTF-8의 경우):
$string =
array(utf8_decode("Düsseldorf"), // Deliberately produce broken string
"Washington",
"Nairobi");
print_r(json_encode($string));
결과:
[null,"Washington","Nairobi"]
원하는 결과:
["D�sseldorf","Washington","Nairobi"]
주의: 끊어진 문자열을 json_encode()로 동작시킬 생각은 없습니다.인코딩 오류를 쉽게 진단할 수 있는 방법을 찾고 있습니다.anull문자열은 도움이 되지 않습니다.
php는 오류를 발생시키려 하지만 display_display를 꺼야 합니다.이것은 이상합니다.왜냐하면display_errors설정은 오류가 표준 출력으로 인쇄되는지 여부를 제어하는 것일 뿐 오류가 트리거되는지 여부를 제어하는 것은 아닙니다.제가 강조하고 싶은 것은, 여러분이 이 모든 것을display_errorson, 다른 모든 종류의 php 오류를 볼 수 있지만, php는 이 오류를 숨길 뿐만 아니라 트리거하지도 않습니다.즉, 에러 로그에 표시되지 않고 커스텀error_handler도 호출되지 않습니다.에러는 발생하지 않습니다.
이를 나타내는 코드는 다음과 같습니다.
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()는 문제가 있는 문자를 초크하여 실패하는 것을 얻을 수 없습니다.//IGNOREflag는 유효한 utf8 문자의 json_encodes 개념과 완벽하게 호환되므로 구매자는 주의해 주십시오.이것은 여전히 엣지가 실패할 수 있기 때문입니다.아, 난 캐릭터 세트 문제가 싫어.
★★★★★
7에는 php 7.2+에 것 .json_encodeJSON_INVALID_UTF8_IGNORE ★★★★★★★★★★★★★★★★★」JSON_INVALID_UTF8_SUBSTITUTE
아직 많은 문서는 없지만, 현시점에서는 이 테스트를 통해 예상되는 동작을 이해할 수 있습니다.https://github.com/php/php-src/blob/master/ext/json/tests/json_encode_invalid_utf8.phpt
.3에는 새로운 「hp 7.3+"가 JSON_THROW_ON_ERRORhttp://php.net/manual/en/class.jsonexception.php 를 참조해 주세요.
이 함수는 문자열에서 잘못된 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);
}
Excel 문서를 json으로 변환한 후 사용하는데, Excel 문서는 UTF8에 있을 수 없기 때문입니다.
유효하지 않은 문자를 보이면서도 유효한 문자로 변환할 수 있는 특별한 합리적인 방법은 없다고 생각합니다.위의 regex를 돌려 비활성 문자를 Unicode 대체 문자인 U+FFD로 대체할 수 있지만, 이는 비활성 문자를 삭제하는 것보다 더 나은 사용자 경험을 제공하지 않습니다.
$s = iconv('UTF-8', 'UTF-8//IGNORE', $s);
이치노나는 왜 php의 사람들이 수정으로 삶을 더 쉽게 만들지 않았는지 모르겠다.json_encode().
위의 방법을 사용하면 데이터에 특수 문자(스웨덴 문자 등)가 포함되어 있어도 json_encode()는 개체를 만들 수 있습니다.
후 데이터를할 수 ('javascript'를 사용합니다).escape(),unescape(),encodeURIComponent(),decodeURIComponent()
php : php (smarty)에서 .에서는 이렇게 사용하고 있습니다.
$template = iconv('UTF-8', 'UTF-8//IGNORE', $screen->fetch("my_template.tpl"));
, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★innerHTML을 사용하다
은 「이행」에 가 있습니다.json_encode()어떤 인코딩으로도 작동하도록 하기 위해서요.
당신이 다루고 있는 모든 문자열의 부호화를 알아야 해요 그렇지 않으면 고통의 세계로 들어갈 거예요
UTF-8은 사용하기 쉬운 부호화입니다.또한 JSON은 UTF-8(http://www.json.org/JSONRequest.html)을 사용하도록 정의되어 있습니다.그럼 왜 사용하지 않는 거죠?
간단한 답변: json_encode() 문자열이 손실되는 것을 방지하는 방법은 문자열이 유효한 UTF-8인지 확인하는 것입니다.
iconv 함수를 사용하는 대신 json_encode를 JSON_UNESCAPED_와 함께 사용할 수 있습니다.UNICODE 옵션( > = PHP5.4.0 )
php 파일 헤더에 "charset=utf-8"을 넣어야 합니다.
헤더('Content-Type: application/json; charset=utf-8');
json 장애에 대한 정보 오류 알림을 받으려면 다음 도우미를 사용합니다.
- 는 일시적으로 커스텀에러 핸들러를 인스톨 하고, 부호화/복호화에 관한 json 에러를 검출합니다.
- 실행 시간을 설정하다오류에 대한 예외
<?php
/**
* usage:
* $json = HelperJson::encode(['bla'=>'foo']);
* $array = HelperJson::decode('{"bla":"foo"}');
*
* throws exception on failure
*
*/
class HelperJson {
/**
* @var array
*/
static private $jsonErrors = [
JSON_ERROR_NONE => '',
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
];
/**
* ! assoc ! (reverse logic to php function)
* @param string $jsonString
* @param bool $assoc
* @throws RuntimeException
* @return array|null
*/
static public function decode($jsonString, $assoc=true){
HelperJson_ErrorHandler::reset(); // siehe unten
set_error_handler('HelperJson_ErrorHandler::handleError');
$result = json_decode($jsonString, $assoc);
$errStr = HelperJson_ErrorHandler::getErrstr();
restore_error_handler();
$jsonError = json_last_error();
if( $jsonError!=JSON_ERROR_NONE ) {
$errorMsg = isset(self::$jsonErrors[$jsonError]) ? self::$jsonErrors[$jsonError] : 'unknown error code: '.$jsonError;
throw new \RuntimeException('json decoding error: '.$errorMsg.' JSON: '.substr($jsonString,0, 250));
}
if( $errStr!='' ){
throw new \RuntimeException('json decoding problem: '.$errStr.' JSON: '.substr($jsonString,0, 250));
}
return $result;
}
/**
* encode with error "throwing"
* @param mixed $data
* @param int $options $options=JSON_PRESERVE_ZERO_FRACTION+JSON_UNESCAPED_SLASHES : 1024 + 64 = 1088
* @return string
* @throws \RuntimeException
*/
static public function encode($data, $options=1088){
HelperJson_ErrorHandler::reset();// scheint notwendg da sonst bei utf-8 problemen nur eine warnung geflogen ist, die hier aber nicht durchschlug, verdacht der error handler macht selbst was mit json und reset damit json_last_error
set_error_handler('HelperJson_ErrorHandler::handleError');
$result = json_encode($data, $options);
$errStr = HelperJson_ErrorHandler::getErrstr();
restore_error_handler();
$jsonError = json_last_error();
if( $jsonError!=JSON_ERROR_NONE ){
$errorMsg = isset(self::$jsonErrors[$jsonError]) ? self::$jsonErrors[$jsonError] : 'unknown error code: '.$jsonError;
throw new \RuntimeException('json encoding error: '.$errorMsg);
}
if( $errStr!='' ){
throw new \RuntimeException('json encoding problem: '.$errStr);
}
return $result;
}
}
/**
HelperJson_ErrorHandler::install();
preg_match('~a','');
$errStr = HelperJson_ErrorHandler::getErrstr();
HelperJson_ErrorHandler::remove();
*
*/
class HelperJson_ErrorHandler {
static protected $errno = 0;
static protected $errstr = '';
static protected $errfile = '';
static protected $errline = '';
static protected $errcontext = array();
/**
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param array $errcontext
* @return bool
*/
static public function handleError($errno, $errstr, $errfile, $errline, $errcontext){
self::$errno = $errno;
self::$errstr = $errstr;
self::$errfile = $errfile;
self::$errline = $errline;
self::$errcontext = $errcontext;
return true;
}
/**
* @return int
*/
static public function getErrno(){
return self::$errno;
}
/**
* @return int
*/
static public function getErrstr(){
return self::$errstr;
}
/**
* @return int
*/
static public function getErrfile(){
return self::$errfile;
}
/**
* @return int
*/
static public function getErrline(){
return self::$errline;
}
/**
* @return array
*/
static public function getErrcontext(){
return self::$errcontext;
}
/**
* reset last error
*/
static public function reset(){
self::$errno = 0;
self::$errstr = '';
self::$errfile = '';
self::$errline = 0;
self::$errcontext = array();
}
/**
* set black-hole error handler
*/
static public function install(){
self::reset();
set_error_handler('HelperJson_ErrorHandler::handleError');
}
/**
* restore previous error handler
*/
static function remove(){
restore_error_handler();
}
}
WordPress는 이 문제를 방지하기 위해 JSON 주위에 래퍼가 있습니다. wp_json_encode의 소스 코드를 볼 수 있지만 요약하면 다음과 같습니다.
$data = [ utf8_decode("Düsseldorf"), "Washington", "Nairobi" ];
foreach ( $data as &$string ) {
$encoding = mb_detect_encoding( $string, mb_detect_order(), true );
if ( $encoding ) {
return mb_convert_encoding( $string, 'UTF-8', $encoding );
} else {
return mb_convert_encoding( $string, 'UTF-8', 'UTF-8' );
}
}
json_encode( $data );
// Result: ["D?sseldorf","Washington","Nairobi"]
재귀 배열, 객체 또는 스칼라가 아닌 데이터에 대해서는 _wp_json_sanity_check에서 보다 자세한 코드를 확인하십시오.
문자열에서 인쇄할 수 없는 문자 제거
$result = preg_replace/[:^print:]]/, , $string];
https://alvinalexander.com/php/how-to-remove-non-printable-characters-in-string-regex/에 의한 솔루션
언급URL : https://stackoverflow.com/questions/4663743/how-to-keep-json-encode-from-dropping-strings-with-invalid-characters
'programing' 카테고리의 다른 글
| grep, awk, sed의 차이점은 무엇입니까? (0) | 2023.05.18 |
|---|---|
| 약속을 돌려주는 각진 공장 (0) | 2023.03.19 |
| PHP fopen() 오류: 스트림을 열지 못했습니다.권한 거부 (0) | 2023.03.19 |
| ESLint broken: 제안이 있는 규칙은 "meta.has Suggestions" 속성을 "true"로 설정해야 합니다. (0) | 2023.03.19 |
| 부트스트랩 파일에서 다른 스프링 프로파일을 올바르게 설정하려면 어떻게 해야 합니까(다른 클라우드 구성 서버를 대상으로 하는 스프링 부트용)? (0) | 2023.03.19 |