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

Add an option to CsvEncoder to omit the header #27447

Closed
tamasd opened this issue May 31, 2018 · 6 comments
Closed

Add an option to CsvEncoder to omit the header #27447

tamasd opened this issue May 31, 2018 · 6 comments

Comments

@tamasd
Copy link

tamasd commented May 31, 2018

In the project I am working on the application on the other end expects the CSV without the headers. It would be nice if I could have an option to omit the header.

@Aerendir
Copy link
Contributor

Aerendir commented Jun 3, 2018

Can you simply remove it with unset($array[0]) before sending the payload to the application on the other end?

@tamasd
Copy link
Author

tamasd commented Jun 4, 2018

Unfortunately not. I send the CSV data itself.

The serializer constructs the headers based on the array keys.

@Aerendir
Copy link
Contributor

Aerendir commented Jun 4, 2018

@tamasd , I think I'm not understanding: you send the CSV file as is or you send the CSV data after having processed the CSV file?

In the first case you should operate on the "other-app" side; if you send data contained in the CSV file, instead, you should remove the header before sending such data.

What is stopping you from removing the first line before processing the data in the CSV (either on your "client" side or on your "other-app" side): I'm missing this point...

@tamasd
Copy link
Author

tamasd commented Jun 4, 2018

To simplify the problem, I send the CSV content in the request body. Ideally, this encoder could encode my simple 2D array into CSV, and I can just send it as is. The "other app" is an external web API, I have no control over that. Basically, I store data in CSV format, and retrieve it (to display to the user), but the data might be changed by the "other app", and they don't need headers, since the format of the CSV is simple.

I can remove the first line of the resulting CSV, and add it back when I receive data, but it is a hacky solution. It would be much simplier if I could do something like $encoder->setHeaders(false);.

Currently I copied relevant parts from this class, but since we use a lot of Symfony components, it would be better if I could reuse this.

@Aerendir
Copy link
Contributor

Aerendir commented Jun 4, 2018

Ok, understood the problem.

Anyway, I think this is not a hacky way: you simply have to process the data for two different purposes:

  1. To send them to the API (without headers)
  2. To store/show data

I think this is not a useful option to be included in the symfony component.

I understand your point, but I think this is not a Serializer's purpose to manipulate data this way: it is your responsibility and you should use the Serializer component as is and then modify data to be sent to the API.

I don't understand why, to only strip out the header, you are copying the class just for this small feature.

In my opinion is much more correct to

  1. Get the array data from the serializer
  2. Save the header in a variable ($header = $data[0])
  3. Remove the header from the array (unset($data[0]))
  4. Send data
  5. Add the header back to the response array (array_unshift($responseArray, $header))
  6. Save

And, more, there is another thing I don't understand: in the database, you save the headers (at least I understand you do from your words): so this means that also if you will remove them with the Serializer, you anyway need to have them somewhere in your code...

@tamasd
Copy link
Author

tamasd commented Jun 4, 2018

It is the other way around. I already have my 2D string array, I convert it to CSV, so I get numbers as headers, basically an extra line of data at the beginning of the string I get from the serializer. I need to remove that line, and add it back when I try to read the data, to be able to use this serializer.

A simple illustration: let's say I have a very simple piece data: [["asdf"]]. If I encode this, I should get asdf only. Instead, I get this:

0
asdf

This happens the other way around as well. Let's say the "other app" has a piece of data with just asdf. If I try to decode this, I get an empty array as a result.

The problem here is that without manipulating the CSV string itself (which is something I am very uneasy to do, since it is the job of the encoder), I cause either data corruption or data loss.

@fabpot fabpot closed this as completed Jan 1, 2019
fabpot added a commit that referenced this issue Jan 1, 2019
…ode) (redecs)

This PR was squashed before being merged into the 4.3-dev branch (closes #29283).

Discussion
----------

[Serializer] CsvEncoder no header option (encode / decode)

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #27447
| License       | MIT
| Doc PR        | -

This PR wants to introduce a new context option for the CsvEncoder, `CsvEncoder::NO_HEADERS_KEY` (boolean), that allows CSV encoding/decoding when you don't have/need a header.

By default this is assumed to be false, so the headers are included in the CSV output or assumed to be present in the CSV input.

When the option is set to true, the following behaviour occurs.

Encoding
===
The following PHP input
```php
array(array('a','b'), array('c', 'd'))
```
will generate this CSV output
```csv
a,b
c,d
```

Decoding
===
Considering the CSV input to be
```csv
a,b
c,d
```
the following PHP array will be returned
```php
array (
  0 => array (
    0 => 'a',
    1 => 'b',
  ),
  1 => array (
    0 => 'c',
    1 => 'd',
  ),
)
```

Commits
-------

0e63c61 [Serializer] CsvEncoder no header option (encode / decode)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants