2

I'm fetching data in React from a MySQL database. MySQL auto-escapes my values including nested objects. I'm using the .json() function on the top-level but i'm not able to use this on sub-levels, nor JSON.parse(response[0].data) will work.

What is the right way of doing this?

 fetch(`http://localhost:3000/getQuiz${window.location.pathname}`, requestOptions)
  .then(response => response.json())
  .then(response => {
    console.log(response)
    //   {
    //     "id": 1,
    //     "url": "asd2q13",
    //     "data": "{name: \"Marie\", answers:[\"1\", \"3\", \"0\"]}"
    // }
    console.log(typeof response)
    // object
    console.log(response[0].data)
    // {name: "Marie", answers:["1", "3", "0"]}
    console.log(typeof response[0].data)
    // string
    console.log(response[0].data.name)
    // undefined
  })
1
  • I assume this is because it does not like {name: "Marie", answers:["1", "3", "0"]} missing quotes around the property names. The JSON spec specifies an object member being string name-separator value (section 2.2) it further goes on to state that A string begins and ends with quotation marks (section 2.5). So the property names in the "JSON" stored in the data property are invalid. Does JSON.parse() throw an error? Commented Nov 11, 2021 at 2:38

2 Answers 2

2

The response.data is not a valid JSON string. You can try:

const response = {
  "id": 1,
  "url": "asd2q13",
  "data": "{name: \"Marie\", answers:[\"1\", \"3\", \"0\"]}"
}
console.log(eval('(' + response.data + ')'))

Or Better:

const response = {
  "id": 1,
  "url": "asd2q13",
  "data": "{name: \"Marie\", answers:[\"1\", \"3\", \"0\"]}"
}

function looseJsonParse(obj) {
  return Function('"use strict";return (' + obj + ')')();
}

console.log(looseJsonParse(response.data))

But,

Warning: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval(). See Never use eval()!, below.

I suggest you serialize the data correctly on the backend. I think the MySQL database driver can do this. Also, see Parsing JSON (converting strings to JavaScript objects)

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, it seems reasonable, I'll do some troubleshooting in the database end.
@RustyJames Updated answer.
0

MySQL (MySQL2) for Node was the big problem here. It's suppose to serialize "automatically", but somehow it ends up all wrong.

If I do JSON.Stringify() explicitly for the nested part before storeing it in the database it works!

    const sendToDatabase = () => {
       let nested = JSON.stringify({ name: "Marie", answers: ["2", "1", "0"] })
       let post = { url: "asd2q13", data: nested} 
       var query = connection.query(
           "INSERT INTO users SET ?  ", post,
           function (error, results, fields) {
               if (error) throw error;
           }
       );
       console.log(query.sql); 
   };

Then I call this on the front end

   console.log(JSON.parse(response[0].data).name)
   // Marie (string)
   console.log(JSON.parse(response[0].data).answers)
   // ["2", "1", "0"] (array)

The raw output from this is

{"name":"Marie","answers":["2","1","0"]}

insted of

{name: \"Marie\", answers:[\"1\", \"3\", \"0\"]}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.