Mongo Realm App函数中EJSON转标准JSON的实现问题
问题根因
aggregate()方法返回的是聚合游标,不是直接的结果数组,直接对游标调用EJSON.stringify()只能得到空对象{},这是你之前转换失败的核心原因。- HTTPS端点选择JSON返回类型时请求失败,是因为MongoDB返回的结果包含
Date、NumberLong、NumberInt等BSON特殊类型,原生JSON序列化无法识别这类类型,直接抛出错误终止请求。 - 选择EJSON返回时出现的
$numberInt、$date等字段是EJSON的类型扩展标记,用于保留BSON类型信息,不属于标准JSON结构。
可直接运行的实现方案
不需要依赖端点的自动序列化逻辑,拿到聚合结果后手动转成数组、格式化字段,再手动设置响应头返回标准JSON即可:
exports = async function (request, response) { const pipeline = [ { '$project': { '_id': 0 } }, { '$group': { '_id': '$vaultId', 'vaultName': { '$first': '$vaultName' }, 'vaultContract': { '$first': '$vaultContract' }, 'prices': { '$push': { 'readingDate': '$readingDate', 'spotPrice': '$spotPrice' } } } }, { '$sort': { '_id': 1, 'readingDate': -1 } } ]; // 聚合返回游标,必须调用toArray()才能拿到实际文档数组 const aggCursor = await context.services .get("mongodb-atlas") .db("mydb") .collection("mycollection") .aggregate(pipeline); const rawResult = await aggCursor.toArray(); // 逐字段转换,完全匹配预期输出结构 const standardResult = rawResult.map(item => ({ vaultId: item._id.toString(), vaultName: item.vaultName, vaultContract: item.vaultContract, prices: item.prices.map(priceItem => ({ readingDate: priceItem.readingDate.getTime().toString(), spotPrice: priceItem.spotPrice.toString() })) })); // 手动设置响应,返回标准JSON response.setStatusCode(200); response.setHeader("Content-Type", "application/json"); response.setBody(JSON.stringify(standardResult)); };
配置说明
- HTTPS端点返回类型直接选择
JSON即可,手动序列化后不存在BSON类型识别问题,不会再请求失败。 - 不建议直接使用
EJSON.stringify序列化返回结果,该方法会保留EJSON类型标记,生成你不需要的冗余字段。 - 时间戳、浮点数统一转成字符串返回,可避免大整数、高精度浮点数在JSON解析时出现精度丢失问题,和预期输出结构完全一致。
- 如果不想逐字段手动映射,也可以先用EJSON做一次正反序列化去掉类型标记,再调整字段格式:
这种方式代码量更少,但灵活性不如手动映射,适合字段结构简单的场景。// 简易转换方式,注意生成的Date是ISO字符串格式,需要额外转成毫秒时间戳 const plainObj = EJSON.parse(EJSON.stringify(rawResult));
内容的提问来源于stack exchange,提问作者justinavery
相关产品推荐
相关产品推荐

