Problems with PHP Json Encode?

Asked

Viewed 916 times

1

something strange is occurring in the output of my function. When using var_dump only in the variable it returns key and value normally. Piece of code:

public function buildGender()
{
    $unknow_name = array();

    foreach ( $this->author_comment as $key => $value) 
    {
        $first_name = split(' ',$value);

        if  ( isset( $this->genders[ trim( $first_name[ 0 ] ) ] ) )
        {                
            $this->gender_comment[$key] = $this->genders[$first_name[0]];
        }
        else
        {
            $this->gender_comment[$key] = '0';
            $unknow_name[] = $first_name[0];
        }

    }

    foreach ( $this->author_reply as $key => $value) 
    {
        $first_name = split( ' ',$value );

        if  ( isset( $this->genders[ trim( $first_name[0] ) ] ) ) 
        {                
            $this->gender_reply[$key] = $this->genders[$first_name[0]];
        }
        else
        {
            $this->gender_reply[$key] = '0';
            $unknow_name[] = $first_name[0];
        }
    }

    foreach ( $unknow_name as $key ) 
    {
        $PDO = Database::connect();
        $SQL = "INSERT INTO sys_name_gender ( name,classification ) VALUES (?,?) on conflict(name) do nothing";
        $DATA = array($key,'0'); 
        $SQL  = $PDO->prepare($SQL);
        $SQL->execute($DATA);
        $PDO = Database::disconnect();
    }

    //var_dump(array_count_values($this->gender_comment)  );
    echo json_encode( array( 'gender_reply' => array_count_values( $this->gender_reply ), 'gender_comment' => array_count_values( $this->gender_comment ) ) );

}

This function takes the first name, compares it with my sorted name base and if it returns a string 0 | 1 | 2. If it is 0 it inserts the name to be classified in the future.

The way out is like this:

{"gender_reply":{"1":3,"0":24,"2":4},"gender_comment":[5341,358,3478]}

would have to stay that way:

{"gender_reply":{"1":3,"0":24,"2":4},"gender_comment":{"1":358,"0":5341,"2":3478}}

in var_dump it correctly shows the keys and values, taking only json_encode

Does anyone know why he formatted this JSON like this?

was like this:

$_gender_reply   = array_count_values( $this->gender_reply );
        $_gender_comment = array_count_values( $this->gender_comment );

        $_zero = $_gender_comment['0']+$_gender_reply['0'];
        $_one  = $_gender_comment['1']+$_gender_reply['1'];
        $_two  = $_gender_comment['2']+$_gender_reply['2'];
        $total = $_zero+$_one+$_two; 

        echo json_encode( array( 'total' => $total-$_zero, '%homem' => number_format($_one/($total-$_zero)*100,'2'), '%mulher' => number_format($_two/($total-$_zero)*100,'2') ) );

It worked perfectly, but I’d like to know why he didn’t mount JSON the right way.

  • Show an example of how to return. Also show an example of what the var_dump test returns()

  • Daniel, I appreciate your interest in helping. In the var_dump it normally shows the key output and value of both, I checked the situation by making one more filter and took the opportunity to put the calculated fields instead of dealing with js. But it is strange this kind of bug, I still investigate the cause of it. I will update in the post.

1 answer

2


When the array indexes are all numerical, the json_enconde() does not return the pair "chave":"valor" and presents only the values, ordered by the index.

A clearer example:

$array = array(0 => 5341, 1 => 358, 2 => 3478);
echo json_encode($array);

return:

{[5341,358,3478]}

If there is a non-numeric key:

$array = array(0 => 5341, 1 => 358, 2 => 3478, 'foo' => 444);

Returns the pair "chave":"valor"

{"0":5341,"1":358,"2":3478,"string":444}

To display array keys with numeric-only indexes, you can use the second parameter with the constant value JSON_FORCE_OBJECT.

$array = array(0 => 5341, 1 => 358, 2 => 3478);
echo json_encode($array, JSON_FORCE_OBJECT);

Return:

{"0":5341,"1":358,"2":3478}

Consult: http://php.net/manual/en/json.constants.php

For questions, I ran a test simulating what is supposedly in the array, as described in the question:

//5341,358,3478
//$arr = array('0', '0', '0', '1', '1', '1');
for ($i = 1; $i <= 5341; $i++) {
    $arr[] = 0;
    if ($i <= 358) {
        $arr[] = 1;
    }
    if ($i <= 3478) {
        $arr[] = 2;
    }
}
//var_dump(array_count_values($arr));
//echo PHP_EOL.PHP_EOL.PHP_EOL.json_encode(array_count_values($arr));
echo PHP_EOL.PHP_EOL.json_encode(array_count_values($arr), JSON_FORCE_OBJECT);

I did this because the array is large, it has 9,000 values approximately. So I thought it could be something with memory, but the result gave what was expected. As the keys are numerical, the json_encode() returns only the values.



Obs: Numeric keys in an array are only integers. Fractional numbers are ignored.

  • Thank you for your cooperation, but there is one question that has not been made clear to me. The variables receive the same type of data, pass the keys as string (although with number, I don’t know if it would be correct). One returns the pair, and the other does not. That’s what’s puzzling me. For 0 | 1 | 2 are internal tags of ours. For unknown, male or female, not array content. But excellent explanation.

  • When you apply the array_count_values(), the numeric indices become of the numeric type, even if in the array they are as strings. But it doesn’t make much sense for the other array to return the keys as if it were an associative array because they are also numerical.

  • Great!!! I forgot about this detail of the array_count_values(), but we stayed in case one works and another doesn’t. Anyway, I’m putting one more foreach and filtering the results and incrementing in another array to not get stuck at this stage.

  • The memory issue of the main array has approximately this amount of record, but it has another array that comes in 60k positions, which breaks the comment for word-by-word analysis. I left the memory limit for script with 512mb, my server has 64gb of RAM and estimate of 10 ~20 simultaneous accesses.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.