automapper icon indicating copy to clipboard operation
automapper copied to clipboard

`skip_uninitialized_values` not working ?

Open TheoD02 opened this issue 1 year ago • 6 comments

I am trying to map a payload for a PATCH endpoint and would like to configure it so that:

  • If a property is uninitialized, it is skipped during the update.
  • If a property is explicitly set to null, it should update the field to null (if the field is nullable).

However, the current behavior of skip_uninitialized_values is not working.

I have also tried using skip_null_values, but this is problematic because it skips both uninitialized and null values. In cases where a field is nullable (e.g., birthdate), this prevents setting a nullable field to null during a PATCH operation.

Example:

Here’s a basic example of my User entity:

class User
{
    private string $name;

    private ?\DateTimeInterface $birthdate = null; // Nullable
}

In a PATCH request, I would like the following behavior:

  • If birthdate is not provided in the payload, it should remain unchanged.
  • If birthdate is explicitly set to null in the payload, it should be updated to null in the entity.

Here’s what the request payload might look like:

{
    "name": "John Doe",
    "birthdate": null
}

Expected Behavior:

  • Properties that are uninitialized (e.g., not provided in the payload) should be skipped in the update.
  • Nullable properties (like birthdate) should be updated to null if explicitly set to null.

Current Behavior:

  • skip_uninitialized_values does not skip uninitialized properties as expected.
  • skip_null_values skips both uninitialized and null values, making it impossible to set a nullable field to null in a PATCH request.

Steps to Reproduce:

  1. Create a User entity with a nullable field (e.g., birthdate).
  2. Attempt to perform a PATCH request where some fields are not provided and others are explicitly set to null.
  3. Observe that uninitialized fields are not skipped correctly, or nullable fields can't be updated to null.

Questions:

  • Is there a way to achieve this behavior using the current options?

TheoD02 avatar Sep 15 '24 22:09 TheoD02

class User
{
    private string $name;

    private ?\DateTimeInterface $birthdate = null; // Nullable
}

When you type property with default value it already initialized on creation, so if you just remove = null it should work as expected.

MrMeshok avatar Sep 16 '24 06:09 MrMeshok

class User
{
    private string $name;

    private ?\DateTimeInterface $birthdate = null; // Nullable
}

When you type property with default value it already initialized on creation, so if you just remove = null it should work as expected.

Thanks for answer :)

Yes for that case, but in case you only want to update partially a resource, if birthdate is present, but name is not. An error will occur because mapper will attempt to map name but is uninitialized

TheoD02 avatar Sep 16 '24 07:09 TheoD02

Can you provide full example with configuration for AutoMapper? I am testing with AutoMapper::create() without any configuration and have no errors

MrMeshok avatar Sep 16 '24 07:09 MrMeshok

Check here: https://phpsandbox.io/n/w5wwq#public/index.php

If I want to only update partially a resource, by setting only birthdate or lastName that will not work because other properties are uninitialized.

If birthdate is set to null or date, it should update value, otherwise it should not, for example

TheoD02 avatar Sep 16 '24 10:09 TheoD02

I see now, for me, it's working because I was mapping from array/stdClass. When I was working with PATCH requests, I did this kind of mapping by hand. Yeah, it's kinda ugly with several if statements, but you can control all the logic

MrMeshok avatar Sep 16 '24 10:09 MrMeshok

I see now, for me, it's working because I was mapping from array/stdClass. When I was working with PATCH requests, I did this kind of mapping by hand. Yeah, it's kinda ugly with several if statements, but you can control all the logic

OK, thanks for your time, make it by hand need some effort that is not really needed in my case ^^

I think the preferable solution will be to split skip_uninitialized_values and skip_null_values to support both approach

TheoD02 avatar Sep 17 '24 11:09 TheoD02

Indeed we don't support skip_uninitialized_values yet, would be a nice addition, will add this to roadmap

joelwurtz avatar Oct 22 '24 09:10 joelwurtz

I started working on this mater and got something working, I need to fix some tests but the feature is there if you wanna take a look at it: https://github.com/jolicode/automapper/pull/200

Korbeil avatar Oct 22 '24 12:10 Korbeil

+1 ... can confirm this is currently not working. are u trying to implement this feature?

jg-development avatar Jan 20 '25 12:01 jg-development

@jg-development Feedback would be appreciated on the related PR: #200

Would you have the opportunity to test it by any chance?

Thanks

damienalexandre avatar Jan 20 '25 12:01 damienalexandre

can do... give me a day or two

jg-development avatar Jan 20 '25 12:01 jg-development

sry for the delayed answer I was kind of sick. could not really check this out. is this still an issue to check?

jg-development avatar Mar 05 '25 07:03 jg-development

@jg-development no worries, we did fixed the issue and released it, you can test it with the last version of AutoMapper :)

Korbeil avatar Mar 06 '25 15:03 Korbeil