Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What's the intended NULL value handling? #233

Open
SvenRtbg opened this issue Mar 21, 2024 · 3 comments
Open

What's the intended NULL value handling? #233

SvenRtbg opened this issue Mar 21, 2024 · 3 comments

Comments

@SvenRtbg
Copy link
Contributor

The default setting is to be strict about NULL values if they are not allowed:

    /**
     * Throw an exception, if null value is found
     * but the type of attribute does not allow nulls.
     *
     * @var bool
     */
    public $bStrictNullTypes = true;

However there is one explicit test case in ArrayTest.php that verifies that NULL inside a JSON array of DateTime is translated to NULL in the final array:

    /**
     * Test for an array of classes "@var ClassName[]" with
     * flat/simple json values (string)
     */
    public function testMapTypedSimpleArray()
    {
        $jm = new JsonMapper();
        $sn = $jm->map(
            json_decode('{"typedSimpleArray":["2014-01-02",null,"2014-05-07"]}'),
            new JsonMapperTest_Array()
        );
        $this->assertIsArray($sn->typedSimpleArray);
        $this->assertCount(3, $sn->typedSimpleArray);
        $this->assertInstanceOf('DateTime', $sn->typedSimpleArray[0]);
        $this->assertNull($sn->typedSimpleArray[1]);
        $this->assertInstanceOf('DateTime', $sn->typedSimpleArray[2]);
        $this->assertSame(
            '2014-01-02', $sn->typedSimpleArray[0]->format('Y-m-d')
        );
        $this->assertSame(
            '2014-05-07', $sn->typedSimpleArray[2]->format('Y-m-d')
        );
    }

Every other test I have seen cares about null values to be either explicitly allowed, or the values are transformed into simple type values that match the required type:

    /**
     * Test for an array of strings - "@var string[]"
     */
    public function testStrArray()
    {
        $jm = new JsonMapper();
        $sn = $jm->map(
            json_decode('{"strArray":["str",false,2.048]}'),
            new JsonMapperTest_Array()
        );
        $this->assertSame(["str", "", "2.048"], $sn->strArray);
    }

One could argue that in the first case, the task is to keep the number of elements, and a side quest is to wrap the strings into DateTime objects if possible, and NULL would not be transferable into a useful DateTime object.

I have not seen another test verifying that non-wrapping objects like JsonMapperTest_Simple are in fact allowing or denying NULL. If I extend the very first test in ArrayTest.php, the added NULL is put into the resulting array just the same:

    /**
     * Test for an array of classes "@var Classname[]"
     */
    public function testMapTypedArray()
    {
        $jm = new JsonMapper();
        $sn = $jm->map(
            json_decode('{"typedArray":[{"str":"stringvalue"},{"fl":"1.2"}, null]}'), # ADDED NULL HERE
            new JsonMapperTest_Array()
        );
        $this->assertIsArray($sn->typedArray);
        $this->assertCount(3, $sn->typedArray); # GET ONE ELEMENT MORE BACK
        $this->assertContainsOnlyInstancesOf(JsonMapperTest_Simple::class, $sn->typedArray); # THAT IS NULL, not the class.
        $this->assertSame('stringvalue', $sn->typedArray[0]->str);
        $this->assertSame(1.2, $sn->typedArray[1]->fl);
    }

It looks like this is likely the reason for the influx in recent "complaints" about array elements being of unexpected type. And I think no matter how we'd fix it, it is a change in behavior that warrants a major version release.

Any insights from anyone?

Referencing #224 here for the same major release.

@dktapps
Copy link
Contributor

dktapps commented May 15, 2024

From what I recall, arrays don't check bStrictNullTypes, which is why I had a problem. @cweiske previously said here that guarding array elements behind this var would require a new major version. Possibly adding an extra bStrictNullTypesInArrays would allow avoiding a BC break, but it seems clunky.

Array elements are generally not subject to the same level of scrutiny as object properties from my experience - see also #225

@cweiske
Copy link
Owner

cweiske commented May 18, 2024

I'd happily accept a patch that extends the bStrictNullTypes option to null values in array - when a new option is added to get the old behavior back (disabled by default), just as described in #211. That way a new major version would be more secure, while software relying on the old behavior could simply activate the new option when updating JsonMapper.

@SvenRtbg
Copy link
Contributor Author

Just to rephrase:

  • bStrictNullTypes defaults to on and will create a breaking behaviour by rejecting array entries that are NULL.
  • A new compatibility flag is added to retain the current behaviour of allowing NULL in arrays.

Let's see if I can get there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants