1

I was trying to save some data (a table) as JSON in my database with AngularJS and PHP. For that, I would want to convert it to string first and then escape special characters (avoiding SQL injection). Once it's saved, I can retrieve it as a string from DB, convert it back to JSON and display in HTML. To simplify it, let's ignore the database and just return the JSON.

The problem occurred with conversions. Just sending string version of JSON, receiving it as is, and parsing it back from string would result in a string. E.g.

var data = {
  "json": JSON.stringify({"A": "B"})   // some random JSON
};
$http.post("php/sendJSON.php", data).  // AJAX post request
then(function(res) {
  console.log( res.data );             // response from back-end
  console.log( JSON.parse(res.data) ); // parsing it to an object
});

and my back-end:

<?php
$postdata = file_get_contents("php://input");
$res = json_decode($postdata);

$json = $res->json;
echo json_encode($json);
?>

My both logs printed ""{\"A\":\"B\"}"" and "{"A":"B"}". So the parsed response had double quotes and JSON.parse didn't turn it into an object. A hack would be to use JSON.parse(JSON.parse(res.data)), but I was wondering if there is a proper way. (Same thing for angular.fromJson(res.data))

Beyond that issue I was interested in escaping the string. (I used mysqli::real_escape_string) But that would add more complexety to parsing. E.g. this time it will be ""{\\\"A\\\":\\\"B\\\"}"" and "{\"A\":\"B\"}" in logs. So I tried to manually unescape it with:

function unEscapeJsonString($value) {
  $escapers = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b");
  $replacements = array("\\", "/", "\"", "\n", "\r", "\t", "\x08", "\x0c");
  $result = str_replace($escapers, $replacements, $value);
  return $result;
}

This finally gave me an object, but once again it felt like a hack, and unescaping still doesn't solve the problem with a double JSON.parse that I needed to use.

The biggest issue with this is when I try to have new lines and white spaces in JSON, {"A":"B \n C"}, it will not parse it twice and always return a string. Another hack for this is to use:

JSON.parse(res.data).replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");

So the question is: What is the correct way of sending JSON as a string, escaping it, and parsing it back to JSON? (Requests: AngularJS -> PHP -> AngularJS)

6
  • you're basically placing a string inside a another JSON object, so it's not so surprising that it gets encoded twice. How about var data = { "json": {"A": "B"} };? Or just var data = {"A": "B"} (and on the server side then just $postdata = file_get_contents("php://input"); $res = json_decode($postdata); echo json_encode($res); to do the back and forth)? I'm not really sure why you're stringifying it at all, or wrapping it inside another object. What's the reason for that? I can't see what value it creates to add those layers of indirection. Just seems to create problems.
    – ADyson
    Commented Apr 19, 2018 at 12:26
  • @ADyson that's pretty much the problem. Sending with $http.post(url, {"A":"B"}) works, it let's me to parse it correctly. But I need to sent more data, and therefore this simple example will not work. That's why it's JSON with stringified JSON inside it. The reason why it's a string is so that I can save it in my database (MySQL 5.5) as some TEXT (medium / var). Commented Apr 19, 2018 at 12:44
  • " But I need to sent more data" ... so make a bigger object, or an array, or whatever structure is needed. But just keep it all as JSON, not randomly stringifying bits of it. So a simple example var data = { "field1": {"A": "B"}, "field2": "XYZ", "field3" [1, 2, 3] }, hopefully you get the idea
    – ADyson
    Commented Apr 19, 2018 at 13:33
  • @ADyson sorry, I meant {"json":{"A":"B"}, "other_data":[...]} (where "json" property is only turned into a string). But either way, if I turn it into a string with JSON.stringify() or json_encode(), I still have to (because it's AngularJS) return it from back-end with echo json_encode($json);, which treats it as an unnecessary, second encoding Commented Apr 19, 2018 at 13:39
  • "if I turn it into a string with JSON.stringify()" ....just....don't. That's my whole point. There seems to be no need for it. That example you gave, will get you all your data at the server side no problem. And if you don't do that, then json_encode will have no issues either.
    – ADyson
    Commented Apr 19, 2018 at 13:42

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.