PHP json_encode with Boolean and decimal values

Asked

Viewed 729 times

4

I have a PHP function that takes data from the database and returns an array with the results. This array by default has all the data as type string, but some fields should be treated as Boolean while others should be treated as values (money) and are of the type decimal.

Later I make use of this data in the HTML page to perform some functions or display data. For example:

  • valor - type _decimal(10,2) - Used to display the value of a product.
  • ativo - tinyint type - Used to mark or not a checkbox.

The array of data I obtain is generated through a query (SELECT) to the database, with this the return comes with all fields in string. This "solves" a part of the problem as it keeps the field valor with the decimal places. The problem starts when I try the conversion, using flags in the json_encode, turn the values back to Boolean (or int), and then I have these two cases:

Case 1: When I use json_encode($resposta,JSON_NUMERIC_CHECK) the column valor loses its decimals and is rounded. Ex: 9.90(string) -> 10(int)

Case 2: When I use json_encode($resposta,JSON_PRESERVE_ZERO_FRACTION ) the column ativo comes as string and I can’t control the checkbox.

Is there any way around this situation?

  • 1

    Strange I just tested, http://ideone.com/EPzTTv did not lose the decimals, and did not put extra parameters on json_encode

  • @Miguel but here you are generating an array manually, what I do is an sql request to the database, where the initial values returned are all in string. Which solves the case of decimal values, because it keeps the houses. However I need to convert in order to use the values of type Boolean, it is in this conversion that I lose the decimals.

  • On "active" why use tinyint instead of "Enum"?

  • 1

    @Danilomiguel, I don’t think this will interfere with the outcome, it would just be a structural change. By the way, several questions I read in the English OS do not even recommend Enum, but tinyint or bit. As the bank already has this structure, I preferred to keep it. But I think that is not the case.

  • 1

    You can post a snippet of code and a var_dump() of the return, including after json_encode?

  • abs() or (bool) in the column ativo Before sending json_encode would not solve in the second case? JSON_NUMERIC_CHECK is transforming its strings into ints but if vc transform before JSON_PRESERVE_ZERO_FRACTION should not interfere with this.

  • Celsom, see this possible solution, http://ideone.com/EPzTTv , here converts the value manually to float and the asset to int

  • @Richerdomoraleida you get a more practical example of how I could do it?

  • @Miguel but in this case, if there is a json_encode then would not "reset" and convert back to string? Because I thought about using a foreach as an alternative, but I think the problem is happening later, when using json_encode. As I use the javascript data later, this step is required.

  • @Celsomtrindade something like this, I didn’t optimize: https://eval.in/673597

  • @That’s what Ricardomoraleida said! That’s the way it is. The only difference is that instead of using JSON_NUMERIC_CHECK I had to use JSON_PRESERVE_ZERO_FRACTION so it returned me value(string) and active(int) as I needed. A question about this.. Is there a method to change the value field instead of the asset? ex.: string($produto['valor']). So I can keep the id (or other int fields) as int as well and only the value as string.

Show 6 more comments

2 answers

5


Bringing here the code I have written in the comments. A simpler solution than trying to coordinate the flags json_encode() is to treat values before moving to function.

In that case, if ativo must be a intor bool and valor should be a string, only need to treat the asset and no flag is required, since in the output of your SQL all values come as string:

$produtos = array(
    array(
        'valor'=> "1.95",
        'ativo'=> '1'
    ),
    array(
        'valor' => '9.90',
        'ativo' => '0'
    ),
);

foreach( $produtos as $produto ) {
    $produto['ativo'] = abs($produto['ativo']);
    $resposta[] = $produto;
}

echo json_encode( $resposta );

Upshot:

[{"valor":"1.95","ativo":1},{"valor":"9.90","ativo":0}]

If you needed to convert a value to string you could also use 'valor' => (string) 1.95 for example.

  • That solves the problem, perfect! But a doubt.. In case I want to convert from int to string, or keep only 1 field as string. Let’s say I have several fields of type int and only the value of type string, it would be easier to convert only the value to string, but if I use (string)$produto['valor'] when doing JSON_NUMERIC_CHECK it loses the string type, if it does not use this flag, the others do not return as int, but as string. Is there any way to solve this? If I explained it correctly...

0

I did a test to demonstrate that there is no difficulty with decimals or booleans when converting to json format.

<?php

$x = array(9.9, 0);

$j = json_encode($x);
?>
<script>
v = JSON.parse('<?php echo $j;?>');
//document.write(v[0]);

if (v[1]) {
    s = 'verdadeiro';
} else {
    s = 'falso';
}

document.write(s);
</script>

Your question does not make clear where and how does the comparisons of boolean values, but by the comments seems to be with Javascript.

For Javascript the value 1 is true and value 0 is false when they are numeric values. If it is a string type v = '0', for example, v will be taken as true.

To "dribble" this can solve with the function parseInt().

<?php

$x = array(9.9, '0');

$j = json_encode($x);
?>
<script>
v = JSON.parse('<?php echo $j;?>');
//document.write(v[0]);

if (parseInt(v[1])) {
    s = 'verdadeiro';
} else {
    s = 'falso';
}

document.write(s);
</script>

As for the decimal value, it can come as a database string that will make no difference.

However, to provide consistency with mathematical operations in Javascript, convert with the function parseFloat() when you need to do mathematical operations.

a = '9.9';
b = 3;
document.write(parseFloat(a) + b);

Just out of curiosity, for PHP it is similar. Just rename the functions. It would be intval() and floatval().

And of course, I disregarded the comparison that checks the type of variable. if (v === true) {, for example, you need another more suitable treatment. But the important thing is that you do not need to touch anything in the json_encode() for both cases.

Browser other questions tagged

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