如何将数据库对象序列化/表示为节点中 API 返回的 JSON

Posted

技术标签:

【中文标题】如何将数据库对象序列化/表示为节点中 API 返回的 JSON【英文标题】:How to serialize / represent database objects as JSON returned by API in node 【发布时间】:2016-04-30 21:41:33 【问题描述】:

我正在使用 express.jssequelize.js 来构建 API。一旦我使用 sequelize 从数据库中检索到一个对象,我想

过滤掉对象属性(例如检索用户,但不将用户的密码哈希呈现给返回的 JSON) 添加新的对象属性

在我从 API 作为 JSON 返回之前。

类似于这些 Rails 库的作用:

Roar Grape Entity

在 node 中最常用的框架是什么?或者sequelize.js / express.js 是否包含执行此操作的功能?

更新

好的,有一个基本的例子,passport.js从DB中获取认证用户的对象,并附加到req.user

router.get('/me/data',
  passport.authenticate('bearer',  session: false ),
  function(req, res) 
    res.status(200).send(req.user);
  
);

这将返回以下 JSON 响应:


  "id": 24,
  "first_name": "John",
  "last_name": "Doe",
  "email": "mymail@example.com",
  "password": "8d23cb9c4827bc06bb30ac47c06af0efbdbeb575001ab7de5387da4085f7184a381335c0f04b45f4a40e5a7042d47ae1e2d29d28fd5be1d534f09ba3db04e8ca",
  "updatedAt": "2016-01-25T09:19:07.422Z",
  "createdAt": "2016-01-25T09:19:07.422Z",
  "data": null

但我想返回这样的东西:


  "id": 24,
  "full_name": "John Doe",
  "email": "mymail@example.com",
  "data": null

不只是在这种情况下,在任何情况下都会呈现用户对象。

【问题讨论】:

您能否举例说明您从数据库中获得了什么,以及您需要 API 返回什么? @DrakaSAN 当然,给你! 【参考方案1】:

最简单的解决方案是在发送之前编辑req.user

功能

render (user) 
    callback(
        "id": user.id,
        "full_name": user.first_name + ' ' + user.last_name,
        "email": user.email,
        "data": null
    );


router.get('/me/data',
  passport.authenticate('bearer',  session: false ),
  function(req, res) 
    render(req.user, function(user) 
        res.status(200).send(user);
    );
  
);

【讨论】:

嗯,有这个可能。您所谓的render 将是用户对象的对象representer。我可能还想要不同的对象表示器。我的问题是人们通常将这种代码放在哪里?在单独的文件中?进入模型文件?我的意思是有人必须已经想到了该问题的通用解决方案以及如何构建文件,对吗? :D @kadrian 我在命名时没有考虑太多。可能有人想到了一个规范,但我自己从未见过或听说过,但我不是专家。我会把它放在路由处理程序附近(因为它只在那里使用,并且直接链接到它)【参考方案2】:

本模块将以Grape Entity 的方式帮助您:

https://github.com/baijijs/entity

例如:

const Entity = require('baiji-entity');

const userEntity = new Entity(
  id: true,
  fullname: true,
  email: true,
  data: true
);

userEntity.parse(req.user);

// And the parsed result will be as below


  "id": 24,
  "full_name": "John Doe",
  "email": "mymail@example.com",
  "data": null

希望对你有帮助。

【讨论】:

【参考方案3】:

好的,你想砍掉一些田地吗?您可以在服务器发送响应之前将其删除。例如使用像 https://www.npmjs.com/package/json-chop 这样的模块,或者如果你使用 mongo db,你可以隐藏这里描述的字段 https://docs.mongodb.org/manual/tutorial/project-fields-from-query-results/

【讨论】:

我正在使用 Postgres。 Chop 看起来很有趣,但它看起来不像 node.js 世界中的“通用”解决方案。不是大多数人都在用吗?【参考方案4】:

在不了解有关设置的更多详细信息的情况下,以下(未经测试的)代码可能会起作用。您可以在查询中针对模型指定属性字段,以过滤掉结果(基于某些条件):

router.get('me/data',function(req, res) 
   db.UserModel.find(
     attributes:['id','first_name','last_name','email','data'],
     where:  id: req.user.id, //put in here whatever you are using to get the info from the database
    )
    .then (function(user) 
        var formatUser = 
            id: user.id,
            full_name: user.first_name + ' ' + user.last_name,
            email: user.email,
            data: user.data,
        ;
        res.json(formatUser);
    
 );

有关详细信息,请参阅以下文档:

http://docs.sequelizejs.com/en/latest/docs/models-usage/

http://docs.sequelizejs.com/en/latest/docs/querying/

【讨论】:

好的,这很好,但是 1) 我必须在每次查找时都指定它,并且 2) full_name 是一个动态属性,如何从 first_namelast_name 中组合它这个案子? 对于发现,这只是利用了sequelize的API。您可以将其抽象为一个函数,也许将其称为 findFilter,并且仅在需要时使用它。对于动态属性,我编辑了代码以调整格式。另一种可能性是您可以在后端更改它,并将结果作为全名返回到服务器

以上是关于如何将数据库对象序列化/表示为节点中 API 返回的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

YAML流程

如何将复杂的 C# 类序列化为 XML 并将其作为 .net 核心 API 的响应发送?

浪潮多节点服务器i48 已成为云数据中心的优选

如何处理 API 有时将属性作为数组返回,有时作为对象返回?

如何在节点获取标头中使用嵌套对象/数组表示法?

如何从远程api序列化制作对象