1

There is a built-in function in PHP or something clean for convert multidimensional array string to array?

String like:

['text', 'te\'"x2t', "text", "te\"x'#t", true, True, [false, False, 100, +100], -100, + 10, -   20]

each value can be strings(+ escaped characters), boolean, int(+sign) and array which make it a multidimensional array.

To:

Array
(
    [0] => text
    [1] => te'"x2t
    [2] => text
    [3] => te"x'#t
    [4] => 1
    [5] => 1
    [6] => Array
        (
            [0] => 
            [1] => 
            [2] => 100
            [3] => 100
        )

    [7] => -100
    [8] => 10
    [9] => -20
)

I wrote a regex for this, which make match valid to the string under those statements. So it will not match if the string not follows after the rules.

(?<_ARRAY>\[\s*(?:(?:(?P>VALUE)|(?P>_ARRAY))\s*,\s*)*(?:(?:(?P>VALUE)|(?P>_ARRAY))\s*)\])

Now I want to save the values as they are, without any changes.

It can be done with eval, but far as I know, eval is risky and I wonder if there is a better solution for this.

if (preg_match('/(?<_ARRAY>\[\s*(?:(?:(?P>VALUE)|(?P>_ARRAY))\s*,\s*)*(?:(?:(?P>VALUE)|(?P>_ARRAY))\s*)\])/', $array))
    eval("\$array = $array;");
Namixo
  • 11
  • 3
  • Possible duplicate of [Convert PHP array string into an array](https://stackoverflow.com/questions/684553/convert-php-array-string-into-an-array) – thmsdnnr Sep 01 '19 at 02:33
  • @thmsdnnr I don't see anything in the duplicate that really helps OP as the answers all depend on having a valid array to begin with. – Nick Sep 01 '19 at 02:38

1 Answers1

1

Update

With a bit of inspiration from this, I've come up with this, which seems to work. Basically the string is split on commas and left and right square brackets that do not occur within quotes, or on single/double quoted strings and each part is processed to turn it into a valid JSON value. The string is then put back together and converted into an array using json_decode:

$str = "['text', 'te\\'\"x,2t', \"tex,t\", \"te\\\"x'#t\", true, True, [false, False, 100, +100], -100, + 10, -   20]";
$parts = preg_split('/\s*("(?:\\\\"|[^"])*"|\'(?:\\\\\'|[^\'])*\')\s*|\s*([,\[\]])\s*/', $str, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($parts as &$part) {
    if (preg_match("/^'(.*)'/", $part, $matches)) {
        $part = '"' . str_replace(array('"', "\\'"), array('\\"', "'"), $matches[1]) . '"';
        continue;
    }
    $lpart = strtolower($part);
    if ($lpart == 'true' || $lpart == 'false') {
        $part = $lpart;
        continue;
    }
    if (preg_match('/^\+\s*(\d+)$/', $part, $matches)) {
        $part = $matches[1];
        continue;
    }
    if (preg_match('/^-\s*(\d+)$/', $part, $matches)) {
        $part = '-' . $matches[1];
        continue;
    }
}
$json = implode('', $parts);
var_dump(json_decode($json));

Output:

array(10) {
  [0]=>
  string(4) "text"
  [1]=>
  string(8) "te'"x,2t"
  [2]=>
  string(5) "tex,t"
  [3]=>
  string(7) "te"x'#t"
  [4]=>
  bool(true)
  [5]=>
  bool(true)
  [6]=>
  array(4) {
    [0]=>
    bool(false)
    [1]=>
    bool(false)
    [2]=>
    int(100)
    [3]=>
    int(100)
  }
  [7]=>
  int(-100)
  [8]=>
  int(10)
  [9]=>
  int(-20)
}

Demo on 3v4l.org

Original Answer

If you convert all the single quotes to double quotes, the string is valid JSON and can be decoded using json_decode:

$str = "['text', 'text', 100, ['text', false], false, ['text', 200], 'text']";
$json = str_replace("'", '"', $str);
print_r(json_decode($json));

Output:

Array
(
    [0] => text
    [1] => text
    [2] => 100
    [3] => Array
        (
            [0] => text
            [1] => 
        )    
    [4] => 
    [5] => Array
        (
            [0] => text
            [1] => 200
        )    
    [6] => text
)

Demo on 3v4l.org

Nick
  • 138,499
  • 22
  • 57
  • 95
  • Ohh, so this is the reason why json_decode didn't work when I tried. However, I can't use it because some of the strings can be with escaped quotes and others with double-quotes. With extra code, it can be done, but I wonder if there is something simpler for this. – Namixo Sep 01 '19 at 02:34
  • @Namixo Can you post the actual string you're working with, or at least a representative example that shows all of the potential edge cases you're dealing with? Otherwise, you can expect simplistic answers that won't likely relate to your use case. Thanks. – ggorlen Sep 01 '19 at 02:42
  • 1
    @Namixo it still ought to be possible to convert your string into valid JSON, although obviously a bit more complex. Other than `eval` or a really complicated splitting on commas (but not within quotes or `[]`) I'm not sure what other options you have. Can you add some other sample data to your question? – Nick Sep 01 '19 at 02:42
  • @Nick I edited the post, do you think eval is a good solution for this? far as I know, eval is evil :-) thanks for helping! – Namixo Sep 01 '19 at 03:07
  • @Namixo is it possible to have commas inside the string values? – Nick Sep 01 '19 at 04:13
  • @Nick Yes, the string can be any character. – Namixo Sep 01 '19 at 04:19
  • @Namixo I've updated my answer with something that I think should work for pretty much any input... – Nick Sep 01 '19 at 05:11
  • @Nick thanks! it works except you have a multi backslash in a row that ignores them. I will dive to it later and give you an update. – Namixo Sep 02 '19 at 17:40