1

I'm writing an API in Next.js to insert data into a MySQL database. The error I'm experiencing relates to a circular reference, but I'm having trouble finding it. Please be aware that I am also using Axios to write this API.

I'm running into the following error:

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Query'
    |     property '_timer' -> object with constructor 'Timer'
    --- property '_object' closes the circle

Here is my API:

import type { NextApiRequest, NextApiResponse } from "next";
import * as pool from "../../../src/utils/dbConnection";
import console from "console";

export default async (req: NextApiRequest, res: NextApiResponse) => {
  const { email, password, firstname, lastname } = req.body as any;
  let conn;
  try {
    conn = await pool.getConnection();
    const rows = await conn.query(
      `INSERT INTO Users(email, password, firstname, lastname) VALUES(?, ?, ?, ?)`,
      [email, password, firstname, lastname]
    );

    res.status(200).json(JSON.stringify(rows));
  } catch (err) {
    console.log(err);
  } finally {
    if (conn) conn.end(); // close connection
  }
};
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Blake Lucey
  • 349
  • 1
  • 7
  • 18
  • 1
    Why do you use `JSON.stringify` in `res.status(200).json(JSON.stringify(rows));`? Should be just `res.status(201).json(rows);` I guess (201 for Created). – pzaenger Aug 24 '22 at 22:03
  • Does your database have a `.toArray()` method that will convert `rows` into an actual array? – jfriend00 Aug 24 '22 at 22:19
  • Which database module on NPM are you using? – jfriend00 Aug 24 '22 at 22:30
  • If `JSON.stringify(rows)` is giving you the circular structure error, then you have to see what `rows` actually is and somehow convert it to a plain array of data that doesn't contain any database stuff in it. – jfriend00 Aug 24 '22 at 22:34

3 Answers3

2

I guess your problem is here: res.status(200).json(JSON.stringify(rows));. So, from the docs of res.json:

Sends a JSON response. This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using JSON.stringify().

Therefore you just need res.json(rows); or maybe res.status(201).json(rows);, where 201 means Created.

Edit:

I think there might be another problem. The query to insert data does not return the inserted rows (if you use mysql). So, please log rows to check its content - and as mentioned by @jfriend00 there could be and properly are some circular references.

However, you can get the id of the inserted row or the number of affected rows for example.

pzaenger
  • 11,381
  • 3
  • 45
  • 46
0
import type { NextApiRequest, NextApiResponse } from "next";
import * as pool from "../../../src/utils/dbConnection";
import console from "console";

export default async (req: NextApiRequest, res: NextApiResponse) => {
  const { email, password, firstname, lastname } = req.body as any;
  let conn;
  try {
    conn = await pool.getConnection();
    const rows = await conn.query(
      `INSERT INTO Users(email, password, firstname, lastname) VALUES(?, ?, ?, ?)`,
      [email, password, firstname, lastname]
    );
    // Error related to your response
    // You should not return in response all function related to your db
    // return rows.rows
    res.status(200).json(rows.rows);
  } catch (err) {
    console.log(err);
  } finally {
    if (conn) conn.end(); // close connection
  }
};
Farhad Aliyev
  • 101
  • 1
  • 4
-1

I personally use safe-json-stringify which has a method to modify objects without stringifying, in case you want a circular-safe object.

https://www.npmjs.com/package/safe-json-stringify

res.status(200).json(safeJsonStringify.ensureProperties(data));

Otherwise, you can look at many other posts on the subject: Stringify (convert to JSON) a JavaScript object with circular reference

About natively removing circulars.

Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245