乐闻世界logo
搜索文章和话题

How to return a complex json response with node js

5 个月前提问
3 个月前修改
浏览次数63

4个答案

1
2
3
4

在Mongoose中,可以通过定义一个schema来保存复杂的JSON数据。Schema是Mongoose中用来定义document的结构和数据类型的方式。当你需要保存嵌套的JSON对象时,可以在schema中使用嵌套的文档(subdocuments)或者Mixed类型。

使用嵌套文档(Subdocuments)

如果JSON结构是已知的,并且你想要在其中嵌套对象,你可以在schema中定义子文档。

javascript
const mongoose = require('mongoose'); const { Schema } = mongoose; // 子文档的schema const childSchema = new Schema({ name: String, age: Number }); // 主文档的schema const parentSchema = new Schema({ children: [childSchema], // 子文档数组 name: String }); // 创建模型 const Parent = mongoose.model('Parent', parentSchema); // 创建一个带有嵌套子文档的实例 const parent = new Parent({ name: 'John Doe', children: [{ name: 'Jane Doe', age: 10 }, { name: 'Jack Doe', age: 8 }] }); // 保存实例 parent.save(function (err) { if (err) return handleError(err); // 已保存 });

使用Mixed类型

如果JSON数据结构不固定或非常复杂,你可以使用Schema.Types.Mixed这个类型来保存任意类型的数据。

javascript
const mongoose = require('mongoose'); const { Schema } = mongoose; // 使用Mixed类型来定义schema const anySchema = new Schema({ any: Schema.Types.Mixed }); // 创建模型 const AnyModel = mongoose.model('Any', anySchema); // 创建一个包含复杂JSON数据的实例 const anyData = new AnyModel({ any: { someField: 'value', nested: { complex: ['data', { can: 'be' }, 'anything'], you: 'like' } } }); // 保存实例 anyData.save(function (err) { if (err) return handleError(err); // 已保存 });

使用Mixed类型时需要注意的是,Mongoose不会自动追踪这种类型的变化,所以如果你更改了Mixed类型字段中的数据,需要手动调用.markModified(path)方法来告诉Mongoose这个字段被修改了。

javascript
anyData.any.nested.complex.push('new data'); anyData.markModified('any'); anyData.save(function (err) { if (err) return handleError(err); // 已保存更新后的数据 });

总结

在Mongoose中保存复杂的JSON数据通常涉及定义一个准确反映数据结构的schema。你可以通过使用嵌套文档来保存已知结构的数据,或者使用Mixed类型来保存不固定或非常复杂的数据。记得对于Mixed类型的字段,在修改后需要调用.markModified()方法以确保正确保存。

2024年6月29日 12:07 回复

On express 3 you can use directly res.json({foo:bar})

shell
res.json({ msgId: msg.fileName })

See the documentation

2024年6月29日 12:07 回复

I don't know if this is really any different, but rather than iterate over the query cursor, you could do something like this:

shell
query.exec(function (err, results){ if (err) res.writeHead(500, err.message) else if (!results.length) res.writeHead(404); else { res.writeHead(200, { 'Content-Type': 'application/json' }); res.write(JSON.stringify(results.map(function (msg){ return {msgId: msg.fileName}; }))); } res.end(); });
2024年6月29日 12:07 回复

[Edit] After reviewing the Mongoose documentation, it looks like you can send each query result as a separate chunk; the web server uses chunked transfer encoding by default so all you have to do is wrap an array around the items to make it a valid JSON object.

Roughly (untested):

shell
app.get('/users/:email/messages/unread', function(req, res, next) { var firstItem=true, query=MessageInfo.find(/*...*/); res.writeHead(200, {'Content-Type': 'application/json'}); query.each(function(docs) { // Start the JSON array or separate the next element. res.write(firstItem ? (firstItem=false,'[') : ','); res.write(JSON.stringify({ msgId: msg.fileName })); }); res.end(']'); // End the JSON array and response. });

Alternatively, as you mention, you can simply send the array contents as-is. In this case the response body will be buffered and sent immediately, which may consume a large amount of additional memory (above what is required to store the results themselves) for large result sets. For example:

shell
// ... var query = MessageInfo.find(/*...*/); res.writeHead(200, {'Content-Type': 'application/json'}); res.end(JSON.stringify(query.map(function(x){ return x.fileName })));
2024年6月29日 12:07 回复

你的答案