Home > front end >  Converting circular structure to JSON, can't see anything circular
Converting circular structure to JSON, can't see anything circular

Time:12-28

I'm learning back-end web development and the course I'm following includes making a REST API for a system that has "tours". I use MongoDB and Mongoose and everything was fine, I was filtering the query according to the parameters and that went well. But then the instructor wanted to put this filtering process (and other query processes) into a class and access them inside this class. After I've done this, I started getting this error. So I know that you can't convert a circular object to JSON, nor can you stringify such an object. But I don't have any... circular objects. Or at least I don't think so. I'm just a beginner, so forgive my mistakes if you will. Here's the code:

const Tour = require("../models/tourModel"); //MongoDB Document Model

class QueryModifier {
    constructor(query, reqQuery) {
        this.query = query;
        this.reqQuery = reqQuery;
    }

    filter() {
        console.log(this.reqQuery);
        const queryObj = { ...this.reqQuery }; //destruct the URL query object into a new object for a hard-copy
        const toBeExcluded = ["page", "sort", "limit", "fields"];

        toBeExcluded.forEach((el) => {
            delete queryObj[el];
        });

        console.log(queryObj);
        let queryStr = JSON.stringify(queryObj);
        queryStr = queryStr.replace(
            /\b(gte|gt|lte|lt)\b/g,
            (matchedStr) => `$${matchedStr}`
        );

        this.query = this.query.find(JSON.parse(queryStr));
        return this;
    }

    sort() {
        if (this.reqQuery.sort) {
            const sortBy = this.reqQuery.sort.replace(/(,)/g, " ");
            this.query = this.query.sort(sortBy);
        } else {
            this.query = this.query.sort("-createdAt");
        }
        return this;
    }

    limitFields() {
        if (this.reqQuery.fields) {
            const fields = this.reqQuery.fields.replace(/(,)/g, " ");
            this.query = this.query.select(fields);
        } else {
            //Default
            this.query = this.query.select("-__v"); //exclude __v
        }
        return this;
    }

    paginate() {
        const page = this.reqQuery.page * 1 || 1;
        const limit = this.reqQuery.limit * 1 || 10;
        const skip = (page - 1) * limit;
        this.query = this.query.skip(skip).limit(limit);

        return this;
    }
}

exports.getAllTours = async (req, res) => {
    try {
        const features = new QueryModifier(Tour.find(), req.query)
            .filter()
            .sort()
            .limitFields()
            .paginate();
        const tours = await features;

        res.status(200).json({ //<------ Error's "position" is after the second dot.
            status: "success",
            results: tours.length,
            data: { tours },
        });
    } catch (e) {
        res.status(404).json({
            status: "failure",
            message: e.message,
        });
        console.log(e);
    }
};

The error is at the place where I commented with an arrow. And here's the error message:

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Topology'
    |     property 's' -> object with constructor 'Object'
    |     property 'sessionPool' -> object with constructor 'ServerSessionPool'
    --- property 'topology' closes the circle
    at JSON.stringify (<anonymous>)
    at stringify (/Users/mirzabicer/Documents/GitHub/complete-node-bootcamp/4-natours/starter/node_modules/express/lib/response.js:1123:12)
    at ServerResponse.json (/Users/mirzabicer/Documents/GitHub/complete-node-bootcamp/4-natours/starter/node_modules/express/lib/response.js:260:14)
    at exports.getAllTours (/Users/mirzabicer/Documents/GitHub/complete-node-bootcamp/4-natours/starter/controllers/tourController.js:84:25)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

I edited that JSON.stringify call to:

let queryStr = '{ "sort": "price,ratingsAverage", "price": { "gte": "300" } }';

So there's literally no JSON.stringify call in my code now. But the error I get is EXACTLY the same.

CodePudding user response:

The error suggests the problem is in tourController.js on line 84. I guess you are calling JSON.stringify on something that is circular on that line. Try removing that JSON.stringify call.

It seems tours is most likely the problem then. I see it is a QueryModifier. I suppose that is probably not the data you want to return from getAllTours.

You should await the features.query, not the features itself.

  • Related