简体   繁体   中英

Either unexpected token or converting circular structure with JSON parsing

I am trying to write a simple client-server testing site to get a better understanding of sending JSON objects to and from both sides.

index.html

<!DOCTYPE html>
<html>
  <title>Hello Express</title>
  <body>
     <h1>Hello, Express!</h1>
     <script type="text/javascript" src="test.js"></script>
     <form>
        <label for="fname">First name:</label><br>
        <input type="text" id="fname" name="fname"><br>
        <label for="lname">Last name:</label><br>
        <input type="text" id="lname" name="lname"><br>
        <label for="age">Age:</label><br>
        <input type="text" id="age" name="age"><br>
      </form>
      <button onclick="postData()">Post Data</button>
  </body>
</html>

test.js

async function postData() {
    // Default options are marked with *
    const response = await fetch('http://localhost:3000/hello', {
      method: 'POST', // *GET, POST, PUT, DELETE, etc.
      mode: 'no-cors', // no-cors, *cors, same-origin
      cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
      credentials: 'same-origin', // include, *same-origin, omit
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },
      redirect: 'follow', // manual, *follow, error
      referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
      body: JSON.stringify({
          name:"dean",
          age:21
      }) // body data type must match "Content-Type" header
    });
    result = JSON.parse(response)
    var para = document.createElement("P");               // Create a <p> element
    para.innerText = result;               // Insert text
    document.body.appendChild(para);
}

server.js

// server.js
var express = require("express");
var bodyParser = require("body-parser");
var app = express();

app.use(express.static("public"));

app.use(bodyParser.urlencoded({ extended: false }));

app.post("/hello", function(req, res) {
    var result = JSON.stringify(req)
    res.send(result);
});

app.listen(3000);

The idea is to eventually make it so that the values entered in the inputs will be converted into a JSON object, sent to the server and then have one of its attributes returned. Right now however, I am simply trying to send a fixed JSON object to the server and get it back. Using this current implementation however gets me a circular structure error. I have attempted other formats to do this but they then result in an unexpected token error (token oa position 1). If anyone can let me know if I am overlooking anything critical please let me know, I will be using this knowledge for a bigger project later on and would prefer to understand it now as opposed to later.

The main issues you're having is that you are not properly parsing JSON payloads on both the client and server. I've added comments with suggestions on how to fix your code, so have a look below.

On the server-side , you should use express.json() and express.urlencoded() middlewares to parse incoming requests with JSON payloads.

const express = require("express");
const app = express();
const port = 3000;

// use `express.json()` and `express.urlencoded` to
// parse incoming requests with JSON payloads
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  next();
});
app.post("/hello", (req, res, next) => {
  // `req.body` is a native object since `express.json()`
  // and `express.urlencoded()` are taking care of the payload,
  // no need for `JSON.parse()` here
  const { firstName, lastName, age } = req.body;

  console.log("firstName", firstName, "lastName", lastName, "age", age);

  // alternatively, using `dot` notation
  console.log(
    "firstName", req.body.firstName,
    "lastName", req.body.lastName,
    "age", req.body.age
  );

  res.status(200).json({
    firstName,
    lastName,
    age,
    receivedAt: Date.now(),
  });
});

app.listen(port, () =>
  console.log(`Example app listening at http://localhost:${port}`)
);

On the client-side , you should call response.json() after your fetch request resolves with some data that's coming back from the server. Make sure you await it since response.json() returns a Promise .

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>
  <body>
    <form><!-- form elements go here... --></form>
    <button onclick="handleOnSubmit()">Post Data</button>

    <!-- display results here... -->
    <div id="result"></div>
  </body>
</html>

Then, in your JavaScript file, do the following:

function handleOnSubmit() {
  const data = { firstName: "John", lastName: "Doe", age: 21 };
  async function postData() {
    try {
      const response = await fetch("http://localhost:3000/hello", {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
        body: JSON.stringify(data),
      });
      // Make sure you call `response.json()` to parse
      // response into native JavaScript object, no need for `JSON.parse()`
      const payload = await response.json();
      const { firstName, lastName, age, receivedAt } = payload;
      const p = document.createElement("p");

      p.textContent = `${firstName}, ${lastName}, ${age}, ${receivedAt}`;
      document.getElementById("result").appendChild(p);
    } catch (error) {
      console.error(error);
    }
  }
  postData();
}

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM