Skip to content
Advertisement

Unescaping a string meant to be JSON nested in JSON in PHP

My server receives JSON data from a real-world device, which is then saved in a MySQL JSON field. Unfortunately, the manufacturer seems to have a bug in their code which causes part of the data to be stringified escaped JSON.

[
  "foo",
  "bar",
  "info",
  {
    "data": "{"parts":[{"id":1,"serial":"19777","type":"NONE","key":""}]}",
    "vendor": "Test",
    "message": "Hello world"
  }
]

Running json_decode even with JSON_UNESCAPED_SLASHES results in a string

Array
(
    [0] => foo
    [1] => bar
    [2] => info
    [3] => Array
        (
            [data] => {"parts":[{"id":1,"serial":"19777","type":"NONE","key":""}]}
            [vendor] => Test
            [message] => Hello world
        )

)

But the expected output is

Array
(
    [0] => foo
    [1] => bar
    [2] => info
    [3] => Array
        (
            [data] => Array
                (
                    [parts] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 1
                                    [serial] => 19777
                                    [type] => NONE
                                    [key] => 
                                )

                        )

                )

            [vendor] => Test
            [message] => Hellow world
        )

)

Since I cannot expect them to release a firmware update any time soon, is there any function I can run on the entire JSON to identify stringified JSON and re-encode the request before saving to MySQL, but not effect other messages that do not have a similar bug?

Advertisement

Answer

Update: turn any nested json data inside $json into associative array:

Recurse through array $arr using function recurse(), to find any elements with json data and json_decode() them to arrive at your expected output:

<?php
$arr = json_decode($json, true);
recurse($arr); // json_decode() any json inside $arr

function recurse(array &$arr)
{
    foreach ($arr as $key => &$value) {
        if (is_array($value)) {
            recurse($value);
        } else {
            if (is_object(json_decode($value))) {
                $value = json_decode($value, true); // turn json into assoc array
            }
        }
    }
}

working demo

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement