Ælex
Ælex

Reputation: 14869

php preg_match_replace using original value

I am trying to iterate a data set in My SQL, and automatically update json strings which have an object member set as Int instead of String. I am just looking for the quickest and simplest way, so I've gotten into regex.

My json should look like this:

{
    "nodeFrom":"0624a5d0-2cca-4a21-88da-3c7969e25754",
    "nodeTo":"db651b3a-3ccd-4014-9c74-33637b2128d3",
    "index":"1",
    "order":"cr"
}

However, due to earlier assumptions (the mother of all...) some in the database have:

{
    "nodeFrom":"0624a5d0-2cca-4a21-88da-3c7969e25754",
    "nodeTo":"db651b3a-3ccd-4014-9c74-33637b2128d3",
    "index":1,
    "order":"cr"
}

Which creates issues in C++ apps accessing this data, due to non-string assertions.

I wrote the following (I am ommiting the mysqli code) which detects where the problem is:

while ( $row = $result->fetch_array(MYSQLI_ASSOC) )
{
    $uuid = $row['uuid'];
    $json = $row["json"];
    $pattern =  '/"index":\d+/';
    $matches = array();
    $count = preg_match_all( $pattern, $json, $matches );
    // NOTE: We need to use preg_replace

    if ( $count > 0 )
        printf ( "found %s json ints in uuid %s \r\n", $count, $uuid );

Now, I need to use preg_match_replace in order to replace all occurances where this pattern is detected, by adding the extra quotes to the digit. All examples I have seen, simply replace one pattern for another, yet in this case, I want the digit, to be replaced by a digit with quotes.

Upvotes: 1

Views: 517

Answers (2)

joshden
joshden

Reputation: 808

As an alternative to a regex, you could also decode the JSON string, modify, and encode back to JSON.

$json = <<<EOD
{
    "nodeFrom":"0624a5d0-2cca-4a21-88da-3c7969e25754",
    "nodeTo":"db651b3a-3ccd-4014-9c74-33637b2128d3",
    "index":1,
    "order":"cr"
}
EOD;

$object = json_decode($json, true);
$object["index"] = strval($object["index"]);
$json = json_encode($object, JSON_PRETTY_PRINT);
echo $json;

Output:

{
    "nodeFrom": "0624a5d0-2cca-4a21-88da-3c7969e25754",
    "nodeTo": "db651b3a-3ccd-4014-9c74-33637b2128d3",
    "index": "1",
    "order": "cr"
}

This could also be done recursively on any arbitrary JSON string:

$json = <<<EOD
[
    {
        "nodeFrom":"0624a5d0-2cca-4a21-88da-3c7969e25754",
        "nodeTo":"db651b3a-3ccd-4014-9c74-33637b2128d3",
        "index":1,
        "order":"cr"
    },
    {
        "otherObject":2,
        "list": [
            12,
            32
        ]
    }
]
EOD;

$arrays = json_decode($json, true);

array_walk_recursive($arrays, function(&$value){
    if (! is_string($value) && ! is_array($value))
    {
        $value = strval($value);
    }
});

echo json_encode($arrays, JSON_PRETTY_PRINT);

Output:

[
    {
        "nodeFrom": "0624a5d0-2cca-4a21-88da-3c7969e25754",
        "nodeTo": "db651b3a-3ccd-4014-9c74-33637b2128d3",
        "index": "1",
        "order": "cr"
    },
    {
        "otherObject": "2",
        "list": [
            "12",
            "32"
        ]
    }
]

Upvotes: 2

Barmar
Barmar

Reputation: 781592

Use a capture group in the regexp and back-reference in the replacement:

$json = preg_replace('/"index":(\d+)/', '"index":"$1"', $json);

Upvotes: 1

Related Questions