ThePerplexedOne
ThePerplexedOne

Reputation: 2950

JSON.parse invalid character with valid JSON?

So, I have an object whose properties also contain json strings within them. When serializing this object, this is the string I get:

[{
    "template": 1,
    "action_json": "{\"id\":\"1\",\"action\":\"An action for all of IT!\",\"date_agreed\":\"2018-08-10\",\"complete_by\":\"2018-08-31\",\"responsible_departments\":[\"8\"],\"responsible_employees\":[\"1629\",\"112\",\"1374\"],\"priority\":\"High\"}",
    "template_json": "{\"columns\":[{\"id\":\"id\",\"title\":\"Task Number\",\"default\":true,\"type\":\"auto\"},{\"id\":\"action\",\"title\":\"Action Agreed\",\"default\":true,\"type\":\"longtext\"},{\"id\":\"date_agreed\",\"title\":\"Date Agreed\",\"default\":true,\"type\":\"date\"},{\"id\":\"complete_by\",\"title\":\"Complete By\",\"default\":true,\"type\":\"date\"},{\"id\":\"responsible_departments\",\"title\":\"Responsible Departments\",\"default\":true,\"type\":\"option\"},{\"id\":\"responsible_employees\",\"title\":\"Responsible Employees\",\"default\":true,\"type\":\"option\"},{\"id\":\"priority\",\"title\":\"Priority\",\"default\":true,\"type\":\"option\",\"options\":[\"High\",\"Medium\",\"Low\"]}]}"
}, {
    "template": 1,
    "action_json": "{\"id\":\"1\",\"action\":\"Action numero uno\",\"date_agreed\":\"2018-08-10\",\"complete_by\":\"2018-08-10\",\"responsible_departments\":[\"8\"],\"responsible_employees\":[\"112\"],\"priority\":\"High\"}",
    "template_json": "{\"columns\":[{\"id\":\"id\",\"title\":\"Task Number\",\"default\":true,\"type\":\"auto\"},{\"id\":\"action\",\"title\":\"Action Agreed\",\"default\":true,\"type\":\"longtext\"},{\"id\":\"date_agreed\",\"title\":\"Date Agreed\",\"default\":true,\"type\":\"date\"},{\"id\":\"complete_by\",\"title\":\"Complete By\",\"default\":true,\"type\":\"date\"},{\"id\":\"responsible_departments\",\"title\":\"Responsible Departments\",\"default\":true,\"type\":\"option\"},{\"id\":\"responsible_employees\",\"title\":\"Responsible Employees\",\"default\":true,\"type\":\"option\"},{\"id\":\"priority\",\"title\":\"Priority\",\"default\":true,\"type\":\"option\",\"options\":[\"High\",\"Medium\",\"Low\"]}]}"
}]

Which is fine, this is valid JSON.

The problem arises when I try to create a JavaScript object by parsing this string (using PHP):

echo "<script>
    var employeeActions = JSON.parse('".json_encode($employeeActions)."');
</script>";

And then I get:

JSON.parse Error: Invalid character at position:33

When inspecting the page once it's loaded, here is what is echoed through my PHP script:

<script>
    var employeeActions = JSON.parse('[{"template":1,"action_json":"{\"id\":\"1\",\"action\":\"An action for all of IT!\",\"date_agreed\":\"2018-08-10\",\"complete_by\":\"2018-08-31\",\"responsible_departments\":[\"8\"],\"responsible_employees\":[\"1629\",\"112\",\"1374\"],\"priority\":\"High\"}","template_json":"{\"columns\":[{\"id\":\"id\",\"title\":\"Task Number\",\"default\":true,\"type\":\"auto\"},{\"id\":\"action\",\"title\":\"Action Agreed\",\"default\":true,\"type\":\"longtext\"},{\"id\":\"date_agreed\",\"title\":\"Date Agreed\",\"default\":true,\"type\":\"date\"},{\"id\":\"complete_by\",\"title\":\"Complete By\",\"default\":true,\"type\":\"date\"},{\"id\":\"responsible_departments\",\"title\":\"Responsible Departments\",\"default\":true,\"type\":\"option\"},{\"id\":\"responsible_employees\",\"title\":\"Responsible Employees\",\"default\":true,\"type\":\"option\"},{\"id\":\"priority\",\"title\":\"Priority\",\"default\":true,\"type\":\"option\",\"options\":[\"High\",\"Medium\",\"Low\"]}]}"},{"template":1,"action_json":"{\"id\":\"1\",\"action\":\"Action numero uno\",\"date_agreed\":\"2018-08-10\",\"complete_by\":\"2018-08-10\",\"responsible_departments\":[\"8\"],\"responsible_employees\":[\"112\"],\"priority\":\"High\"}","template_json":"{\"columns\":[{\"id\":\"id\",\"title\":\"Task Number\",\"default\":true,\"type\":\"auto\"},{\"id\":\"action\",\"title\":\"Action Agreed\",\"default\":true,\"type\":\"longtext\"},{\"id\":\"date_agreed\",\"title\":\"Date Agreed\",\"default\":true,\"type\":\"date\"},{\"id\":\"complete_by\",\"title\":\"Complete By\",\"default\":true,\"type\":\"date\"},{\"id\":\"responsible_departments\",\"title\":\"Responsible Departments\",\"default\":true,\"type\":\"option\"},{\"id\":\"responsible_employees\",\"title\":\"Responsible Employees\",\"default\":true,\"type\":\"option\"},{\"id\":\"priority\",\"title\":\"Priority\",\"default\":true,\"type\":\"option\",\"options\":[\"High\",\"Medium\",\"Low\"]}]}"}]');
</script>

Upvotes: 0

Views: 2084

Answers (1)

Quentin
Quentin

Reputation: 944114

The text you output from json_encode will be passed through the parser for JavaScript string literals before it gets passed through JSON.parse.

Since JSON and JS string literals use the same escape characters, this will break it! You are mashing up ' characters and data to try to construct a JS string literal programmatically, but the data includes characters with special meaning in JS.

"{\"i

That shows character 33. The JS string literal \" will be parsed putting an unescaped " in the string.

Forget about using JSON.parse. Forget about trying to pass JSON to the browser. Remember that JSON and JavaScript literal syntax are more or less the same thing:

<script>
var employeeActions = <?php echo json_encode($employeeActions); ?>;
</script>

Upvotes: 3

Related Questions