1
foreach ($results as $v)
{
    $k = str_replace('profile.', '', $v[0]);
    $data->profile[$k] = json_decode($v[1], true);

    if ($data->profile[$k] === null)
    {
        $data->profile[$k] = $v[1];
    }
}

I came across these lines of code, they are in Joomla's 'profile' plugin, in the profile.php file. The $result here is an array of key-value pairs of user profile fields, loaded from this table enter image description here

You can see the values are mostly normal strings or numbers.

Since it is unlikely that the users will enter JSON strings here, then why use json_decode here?

Is there any special purpose that I am missing here?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
shenkwen
  • 3,536
  • 5
  • 45
  • 85
  • "it is unlikely"...but not impossible, you think?? If it's not impossible, or it's even explicitly encouraged either in the UI or the documentation, then it would make sense to take the precaution of decoding it. json_decode has no other purpose than decoding json. – ADyson Sep 06 '20 at 21:50
  • Then what is the purpose of the lines following json_decode? – shenkwen Sep 06 '20 at 21:54
  • To set the variable normally, if decoding it as json fails (i.e. because the content of the field isn't valid json. json_decode returns null if it fails, so hence the test for null). – ADyson Sep 06 '20 at 21:56

2 Answers2

2

The use of json_decode() on data that is expected to be scalar (non-iterable) might seem mostly redundant because strings, integers, and floats in most cases will be unaffected.

There are some fringe cases like:

  1. Strings containing escaped forward slashes
  2. Strings containing multibyte characters
  3. Strings containing boolean-expressions as strings that will be used as boolean type
  4. Strings containing numeric-interpreted values that will be used as integer/float type
  5. ...there may well be more cases that I am not considering

Here is a non-exhaustive Demo:

$tests = [
    'true',
    null,
    '123',
    123,
    json_encode('1/2'),
    json_encode('База данни грешка')
];

foreach ($tests as  $test) {
    echo var_export(json_decode($test, true)) . "\n---\n";
}

Output:

true                       #now boolean type
---
NULL
---
123                        #now integer type
---
123
---
'1/2'                      #previously had escaped slash in storage
---
'База данни грешка'        #previously mutated as unicode expressions in storage
---

So in some cases, encoding-storing-decoding creates stability across environments that might otherwise experience "hiccups". In other cases, it may be a workaround to render a strings value as a boolean when the environment does not allow the storage of a boolean type value.

All this said, allowing json type data in customizable fields affords Joomla and its users greater utility when handling complex/unexpected data structures / values.

p.s. the condition:

if ($data->profile[$k] === null)
{
    $data->profile[$k] = $v[1];
}

is just a matter of Joomla trying to do some mopping up when the expected outcome failed because the value was not appropriately json_encoded before going into storage (...accommodating bad development/data or perhaps prior versions of Joomla that were not json_encoding).

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
1

JSON is used here to allow storing different data types (including arrays and objects) and restoring them to correct types in the code while keeping the code for handling data minimal. I.e. there's no special handling for specific fields, everything is done in a simple loop.

Sharky
  • 419
  • 2
  • 8