PHP 배열에서 원소삭제 후 JSON 인코딩하면 객체가되버리는 문제 해결하기


이 문제는 원인만 알면 해결책은 간단합니다. 하지만 제목처럼 되버리는 이유를 알기가 쉽지가 않습니다. 저처럼 기초가 부족하면 더더욱 ㅜㅜ;;

일단 배열이 아래와 같이 있다고 가정해 보겠습니다.

$a1 = [192,193,194,195]; 
var_dump($a1);
$s1 = json_encode($a1);
echo "JSON ENCODED: " . $s1 ."\n";


// 위 문장들의 결과는 아래와 같습니다.
array(4) {
  [0]=>
  int(192)
  [1]=>
  int(193)
  [2]=>
  int(194)
  [3]=>
  int(195)
}
JSON ENCODED: [192,193,194,195]

위와 같이 결과는 배열형태로 JSON 인코딩 됩니다 그리고 인코딩된 $s1 값도 다시 json_decode($s1, true) 로 하면 원래 배열 그대로 디코딩됩니다.

이제 이 상태에서 배열의 원소(element) 한 개를 삭제하려면 unset() 함수를 사용하면 됩니다. 예를 들어 위 배열에서 3번째 원소를 삭제해 보겠습니다. (마지막 원소는 제외하고 다른 원소들을 제거하는 경우 문제가 발생합니다.)

$a1 = [192,193,194,195]; 
unset($a1[2]);
var_dump($a1);
$s1 = json_encode($a1);
echo "JSON ENCODED: " . $s1 ."\n";


// 위 문장들의 결과는 아래와 같습니다.
array(3) {
  [0]=>
  int(192)
  [1]=>
  int(193)
  [3]=>
  int(195)
}
JSON ENCODED = {"0":192,"1":193,"3":195}

삭제 후 var_dump() 결과에서 배열의 첨자를 잘 보면 마지막 원소의 첨자가 2가 아닌 3으로 나옵니다!!! 첨자값도 같이 개별로 저장하고 있기 때문에 중간에 원소를 삭제하면 첨자가 순서대로 나열되지 않고 중간에 비어있게 됩니다. PHP 의 배열은 보통 연관배열 형식으로 거의 배열을 맵(map)처럼 취급하다보니 나오는 문제입니다. JSON 인코딩을 해보면 의도와는 다르게 자바스크립트의 객체형태로 인코딩됩니다.

물론 JSON 인코딩인 아닌 단순 foreach 구문을 사용한다면 크게 문제가 안될 수도 있습니다. 하지만 JSON 인코딩에서는 배열로 변환하지 못하는 원인이 됩니다.

이 문제를 해결하려면 아래와 같이 간단히 array_values() 함수를 쓰면 됩니다.

$a1 = [192,193,194,195];
unset($a1[2]);
$a2 = array_values($a1); 
$s1 = json_encode($a2);
var_dump($a2);
echo "JSON ENCODED = " . $s1 . "\n";


// 위 문장들의 결과는 아래와 같습니다.
array(3) {
  [0]=>
  int(192)
  [1]=>
  int(193)
  [2]=>
  int(195)
}
JSON ENCODED = [192,193,195]

이제는 JSON 인코딩해도 정상적으로 배열로 인코딩됩니다. ^^

첨부자료

  1. https://stackoverflow.com/questions/3869129/php-json-encode-as-object-after-php-array-unset