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

[Serializer] csv_headers not working as expected #55048

Open
Seb33300 opened this issue May 18, 2024 · 3 comments
Open

[Serializer] csv_headers not working as expected #55048

Seb33300 opened this issue May 18, 2024 · 3 comments

Comments

@Seb33300
Copy link
Contributor

Seb33300 commented May 18, 2024

Symfony version(s) affected

7.0.7

Description

The CsvEncoder has an option to specify the CSV headers, but it doesn't look to work as expected.

When specifying header, the CSV is generated with new columns added.

How to reproduce

$contextBuilder = (new CsvEncoderContextBuilder())
    ->withContext((new ObjectNormalizerContextBuilder())->withAttributes(['firstName', 'lastName']))
    ->withHeaders(['Prénom', 'Nom'])
    ->withDelimiter(';')
;

$csv = $serializer->serialize([array of entities], 'csv', $contextBuilder->toArray());

Result:

Prénom;Nom;firstName;lastName
;;Entity first name;Entity last name

Expected result:

Prénom;Nom
Entity first name;Entity last name

Possible Solution

Probably something wrong here:

$headers = array_merge(array_values($headers), array_diff($this->extractHeaders($data), $headers));

Additional Context

No response

@Seb33300
Copy link
Contributor Author

Seb33300 commented May 18, 2024

Just found the PR that introduced the csv_headers option.
It was not intended to be used to change the header labels but only to reorder columns.

I may open a PR to change that behaviour with something like this:

If the key of the array passed to csv_headers is a string, then use that key as the header's label.

$contextBuilder = (new CsvEncoderContextBuilder())->withHeaders([
    'Prénom' => 'firstName',
    'Nom' => 'lastName',
    'Nested field label' => 'nested.field',
]);

We should be able to keep BC like this. What do you think?

@valtzu
Copy link
Contributor

valtzu commented Jun 2, 2024

I think your example would work fine if you added #[SerializedName]/#[SerializedPath] attributes into your entity class:

class YourEntity
{
  #[SerializedName('Prénom')]
  public string $firstName;

  #[SerializedName('Nom')]
  public string $lastName;
}

Of course it may be a design decision to not want to do that, especially until #53858 is implemented.

Anyway, I don't see any bug here, in your serializer context you've defined

  1. Only serialize firstName & lastName properties from your entity
  2. Treat first column in csv as Prénom and 2nd column as Nom

1 & 2 do not know anything about each other, no mapping is supposed to be happening apart from name converter.

@Seb33300
Copy link
Contributor Author

Seb33300 commented Jun 2, 2024

I did not know about the SerializedName and yes, it works as expected.

However, since i want to set the label only when serializing into CSV, I do not want to use attributes on entities (looks like I cannot specify that the names should be used only for CSV).
And I cannot find how to pass the labels in context builder.

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

Successfully merging a pull request may close this issue.

3 participants