Sequelize 如何解决 JSON 字段序列化和反序列化的问题

作为一个 Node.js 中常用的 ORM 框架,Sequelize 提供了一种非常方便的方式来操作数据库,使得前端开发人员可以快速的开发应用程序。然而,在 Sequelize 中,像 JSON, ARRAY 这类复合类型的字段,稍不注意就容易出现序列化/反序列化异常的问题。本文将介绍 Sequelize 是如何解决 JSON 字段序列化和反序列化的问题,并提供一些相关的解决方案。

问题描述

在 Sequelize 中,定义模型时经常会用到 JSON 字段,例如:

-------------- - ------------------- ---------- -
  ----- ------- - --------------------------- -
    ----- -
      ----- ----------------
    --
    ----- -
      ----- --------------
    -
  ---

  ------ --------
-

其中,info 字段是一个 JSON 类型。在插入数据时,可以直接将对象(JSON)传入该字段:

----- ---- - -
  ----- -----
  ----- - ---- --- ------- ------ -
--

----- ------- - ----- ---------------------

这样,数据就会被保存到数据库中。但是,当查询 Model 时,我们希望得到的 info 字段应该是一个 JSON 对象,而不是字符串,因此需要对其进行反序列化。同样,当插入 Model 时,我们也希望可以直接传入一个 JSON 对象,而不是手动调用 JSON.stringify() 方法序列化后再存储。

这就是 Sequelize 中序列化/反序列化 JSON 字段时会遇到的问题。

Sequelize 解决方案

Sequelize 提供了两个属性:getterMethodssetterMethods,通过这两个属性,我们可以自定义序列化和反序列化过程,以达到我们的目的。

具体来说,getterMethods 可以在从数据库取出时,对字段进行反序列化(取出来的是字符串,需要转化为对象),setterMethods 可以在存入数据库时,对字段进行序列化处理(存入的是对象,需要转化为字符串)。

以我们上面的模型为例:

----- ------- - --------------------------- -
  ----- -
    ----- ----------------
  --
  ----- -
    ----- ---------------
    ----- - -- ----
      ------ --------------------------------------
    --
    ---------- - -- ---
      ------------------------- -----------------------
    -
  -
---

这样,我们就可以直接使用 JSON 对象直接传入 Model 中了:

----- ------- - ----- ----------------
  ----- -----
  ----- - ---- --- ------- -------- -
---

同样地,当我们查询数据时,得到的也是一个 JSON 对象了:

----- ------- - ----- ----------------- ------ - ----- ---- ----
-------------------------- -- - ---- --- ------- -------- -

序列化/反序列化自定义方法

在有些场景下,可以通过 getterMethodssetterMethods 来实现序列化/反序列化,但是有些情况下,我们需要更加复杂的自定义方法来处理复合类型的字段。

在这种情况下,我们可以定义一个自定义的序列化器,并将其作为配置项传入 Sequelize。

例如,我们可以定义一个将 Date 类型的字段序列化到 ISO 8601 标准的序列化器:

----- ------ - ------------------

-------- ------------------- -
  ------ ---------------------------  
-

-------- -------------------- -
  ------ --- ----------
-

----- ----------- - -
  ----- -
    ---- --------------
    ---- ---------------
  -
--

----- --------- - --- -----------
  -------- --------
  --------- --------
  --------- ----------
  --------- --------------
  ----- ------------
  ----- -----
  ------- -
    ----------- -----
    -------- ----------
    -------- ---------------------
    ---------------- -----
    ------------ -----
    -------- ----------
    -------- ---------------------
    ------- ---------
    ----------- ------
    ------------ -----
    --------------- -----
    -------- -----
    ---------- -------------
    ---------- -------------
  --
  ---------- --------- -- -
    -- -------- -- --------------------------- - -- -
      --- ------ --- ------ -- ------------------------ -
        -- ------------------------------------------ -
          ---------- - ----------------------------------------------------
        -
      -
    -
  --
  ------------- --------- -- -
    -- -------- -- --------------------------- - -- -
      --- ------ --- ------ -- ------------------------ -
        -- ------------------------------------------ -
          ---------- - ----------------------------------------------------
        -
      -
    -
  -
---

这样,在使用 Sequelize ORM 操作数据库时,如果其列值类型为 Date,它会先由 Sequelize 内部调用熟悉的 toPrimitive() 方法获取 Date 的原始值,并将该值传递给自定义的 set 转换器。在提供了一些特有的参数后,它返回一个新的序列化后的字符串并在进行 SQL 查询时包含该值。

同样地,查询时,该序列化器会首先由 Sequelize 调用 getStatus() 方法,然后它将原始的 Date 字符串传递给自定义的 get 转换器。构造资源实例时,通过调用熟悉的函数将值更改为期望类型。

结论

序列化和反序列化常常是在数据库和应用程序中传输 JSON 类型和数组类型的数据时需要进行的操作。在 Sequelize 中,我们可以通过自定义 getterMethodssetterMethods 的方式实现简单的序列化和反序列化操作。对于更加复杂的数据类型,我们可以通过自定义的序列化器来实现。这些方式都可以帮助我们在应用中更好地处理复合类型数据。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6719f7c99babaf620f9fdf42