javascript – 为什么类型为ObjectID(MongoDB)的会话参数转换为字符串?

我写了以下测试代码来说明我的问题:

var express     = require("express"),
    MongoStore  = require("connect-mongo")(express),
    mongoose    = require("mongoose"),
    config      = require(process.cwd() + "/src/config");

exports.run = function() {
    console.info("running http server");

    //create a new HTTP server
    var server = express();

    //sessions
    server.use(express.cookieParser(config.sessions.secret));
    server.use(express.session({
        secret: config.sessions.secret,
        key: config.sessions.key,
        proxy: true,
        cookie: {maxAge: config.sessions.maxAge, signed: true},
        store: new MongoStore({
            mongoose_connection: mongoose.connection
        }, onStoreSetup)}));

    //create a test ObjectID parameter
    var testObjId = new mongoose.Types.ObjectId("522bb0205a259c636c000006");
    server.get("/", function(req, res) {
        if (req.session && req.session.testObjId) {
            res.send("req.session.testObjId now has type " + typeof req.session.testObjId + " - WHY A STRING?");
        }
        else {
            req.session.testObjId = testObjId;
            req.session.save(function(err) {
                if (err) throw err;
                res.send("req.session.testObjId has type " + typeof req.session.testObjId + " - an Object, as expected - NOW REFRESH THIS PAGE");
            });
        }
    });

    //listen for incoming connections once session store is setup
    function onStoreSetup() {
        console.info("mongo session store connected");

        server.listen(config.http.port);
        console.info("http server listening on port %d", config.http.port);
    }
};

首先,它将类型为ObjectId的变量(来自MongoDB native)写入服务器端会话存储.然后,当您刷新页面时,将使用会话,并且参数的类型突然变为字符串.

简而言之,如果运行上面的代码,将显示以下内容:

>访问/

响应:req.session.testObjId有类型对象 – NOW REFRESH THIS PAGE
>再次访问/

响应:req.session.testObjId现在有类型字符串 – 为什么是STRING?

为什么它变换为字符串?

最佳答案 默认情况下,MongoStore会根据“stringify”选项将会话数据转换为JSON.
Here’s a link to the relevant source code. JSON仅支持基本的JavaScript数据类型(String,Number,boolean等),而不支持ObjectId等自定义对象类型.要更改此设置,请在实例化MongoStore时在选项中传递stringify:false.

更新评论中的后续行动

is there any downside to setting stringify: false?

所以请记住,JSON支持大多数应用程序的足够丰富的数据类型集. JSON的优势在于它可以使代码可移植到其他会话存储选项,而依赖完整的ObjectId实例和字符串会将代码耦合到mongodb而没有太多好处.

> JSON

>便携式
>无论如何,JSON和MongoDB都不会给你域名对象,所以KISS
> ObjectId字符串与==和===一起正常工作. ObjectId实例需要特殊处理以避免可怕的instance1 === instance2评估为false陷阱,即使它们表示相同的基础值.

> MongoDB文档

>获得真实的约会
> ObjectId实例(顺便说一句,我认为它实际上不如字符串有用)
>可能更好的查询选项

因此,任何一种方法都是可行的,并且需要权衡利弊.我会使用默认行为,除非/直到你强烈需要stringify:false.

I think Mongo is capable of storing any object?

好吧,让我们准确一点.存在由javascript标量数据类型构成的纯数据对象,然后存在具有行为的函数,方法和对象. mongodb ObjectId不仅仅是纯数据.它表示二进制值,可以存储为十六进制字符串或二进制数,但它将其包装在具有与之关联的特定方法和功能的实例中. JavaScript支持一组类型,JSON是其中的一个子集(没有函数,其他限制等),而mongodb有另一个类似于JSON但不相同的集合.

点赞