When using PHP
s str_getcsv
-function numbers will be treated as strings:
<?php
$csv = str_getcsv('0,1.2,"string"');
var_dump( $csv );
/* result: array(3) {
[0]=>string(1) "0"
[1]=>string(3) "1.2"
[2]=>string(6) "string"
} */
/* DESIRED result: array(3) {
[0]=>int(0)
[1]=>float(1.2)
[2]=>string(6) "string"
} */
The same is true for the fgetcsv
-function. How to overcome this issue without iterating over the array afterwards and convert back each and every value manually - so to say.
Just to make it very clear - I'm not after a workaround like:
<?php
$csv = str_getcsv('0,1.2,"string"');
foreach ( $csv as &$v ) if ( is_numeric( $v ) ) $v += 0;
var_dump( $csv ); // desired result
as I'm dealing with quite a bit of data performance is a thing in my case.
Seems like unfortunately there is no other way than doing a workaround! There are some options to do it and there is not "the one way to go". Depending on each usecase there might be different solutions. For my situation I will use the following code.
<?php
$csv = '0,1.2,"string"';
json_decode( "[$csv]", true );
But be aware that this will fail with multiline values at least!
Here are some tests:
<?php
$csv = '0,1.2,"string"';
var_dump(
json_decode( "[$csv]", true ) // works
, str_getcsv( $csv ) // converts everything to string
);
/*
array(3) { json_decode
[0]=>int(0)
[1]=>float(1.2)
[2]=>string(6) "string"
}
array(3) { str_getcsv
[0]=>
string(1) "0"
[1]=>
string(3) "1.2"
[2]=>
string(6) "string"
}
*/
$csv = '", as value in ,-separated csv"';
var_dump(
json_decode( "[$csv]", true ) // works also when separator is part of value
, str_getcsv( $csv ) // works also when separator is part of value but converts everything to string
);
/*
array(1) { json_decode
[0]=>string(29) ", as value in ,-separated csv"
}
array(1) { str_getcsv
[0]=>string(29) ", as value in ,-separated csv"
}
*/
$csv = '0,"value
with multiline"';
var_dump(
json_decode( "[$csv]", true ) // doesn't work as JSON can't handle multilines
, str_getcsv( $csv ) // works also with multilines but converts everything to string
);
/*
NULL json_decode
array(2) { str_getcsv
[0]=>string(1) "0"
[1]=>string(21) "value
with multiline"
}
*/
A very robust way seems to be the version from my original question as it relies on the native str_getcsv
-function and converts to appropriate types back afterwards. Performancewise this doesn't sound ideal to me but this should be only a concern when dealing with very heavy strings (which is the case for me).
<?php
$csv = str_getcsv('0,1.2,"string"');
foreach ( $csv as &$v ) if ( is_numeric( $v ) ) $v += 0;