5

I have the following code:

$myAwesomeArray = array(
    'value1',
    'value2',
    'value3',
    'value3',
    'value4',
    'value4'
);

$z = json_encode(array('all' => $myAwesomeArray));
var_dump('before', $z);

$myAwesomeArray = array_unique($myAwesomeArray);

$z = json_encode(array('all' => $myAwesomeArray));
var_dump('after', $z);

So there is an array implicitly indexed by integer keys which contains some duplicate values. It's important to have duplicate values, otherwise the behaviour described below will not occur.

As you can see, I convert in JSON both the array and the result of passing it through array_unique() function.

The output I expect to see is something like:

string(6) "before"
string(63) "{"all":["value1","value2","value3","value3","value4","value4"]}"
string(5) "after"
string(45) "{"all":["value1","value2","value3","value4"]}"

However I see this instead:

string(6) "before"
string(63) "{"all":["value1","value2","value3","value3","value4","value4"]}"
string(5) "after"
string(61) "{"all":{"0":"value1","1":"value2","2":"value3","4":"value4"}}"

Apparently the function does indeed remove the duplicate values, but it changes the keys from integers to strings, at least that's what json_encode() sees them.

Another weird behaviour is that if, after passing the array through array_unique(), I do this:

var_dump(array_keys($myAwesomeArray));

then the printed are marked with type int in the output:

array(4) {
  [0]=> int(0)
  [1]=> int(1)
  [2]=> int(2)
  [3]=> int(4)
}

which does not match with what json_encode() is outputting.


I read everything I could find about array_unique() and can't figure out why this happens.

I tested the code above on a Windows 7 machine using PHP 5.3 and PHP 5.6 with no difference in behaviour/output.

Is this a bug? Should I report it as such? Or is this normal behaviour?

3
  • It removed the third element, thus PHP makes it an object instead of a simple array. You could run the array through array_values to reindex it. Commented Feb 17, 2017 at 8:53
  • @CharlotteDunois Yes, that's what I did to obtain the behaviour I wanted, but it still may be a bug. Maybe I'll take a look in the actual implementation of array_unique() to see what's going on, maybe it's intentional behaviour. Commented Feb 17, 2017 at 8:54
  • No, it's not a bug. In PHP arrays can have any keys you want, in Javascript they're number-indexed starting from 0, therefore you can't skip any number-index (in your example, 3), thus you get an object. Commented Feb 17, 2017 at 8:56

3 Answers 3

5

When you use array_unique, the keys will remain, the resulting array is not re-indexed.

That is no problem in php but in javascript an array has - by definition - 0-indexed, sequential keys.

So when you generate your json, php recognizes that the keys are not valid javascript array keys and converts your array to an object. This is correct.

If you want your "expected" results, you need to re-index your array:

$z = json_encode(array('all' => array_values($myAwesomeArray)));
                                ^^^^^^^^^^^^ generate a new array with just the values
Sign up to request clarification or add additional context in comments.

5 Comments

But if they're numerical keys, does it really matter if the keys are not sequential ? Can't it just ignore it this case?
@RaduMurzea No, it can't. You might have created the array on purpose like that, so PHP can't just simply ignore it.
@RaduMurzea Also note that array_unique does not convert the keys to string keys as you mentioned in your title, it is json_encode that needs to generate valid json with the information you give it.
Subtle but apparently very relevant difference. Thanks.
@RaduMurzea It is caused by the different definitions of arrays in the different languages.
1
$myAwesomeArray = array_values(array_unique($myAwesomeArray, SORT_REGULAR));

This is not an ideal solution, but effective in this situation.

Comments

0

Use this

$myAwesomeArray = array_keys(array_flip($myAwesomeArray));

instead of line

   $myAwesomeArray = array_unique($myAwesomeArray);

This is as per your requirement.

Give it a try, this should work.

You will get alternative of this link

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.