Node-redis: 散列中空值的序列化

创建于 2013-06-13  ·  19评论  ·  资料来源: NodeRedis/node-redis

当通过hset 设置的key 的值为null 时,将其序列化为字符串“null”。 通过hgetall获取hash时,返回对象中对应的值为字符串“null”而不是null。

Feature Request v4

最有用的评论

我意识到 node-redis 不会对从 redis 检索到的字符串值进行任何数据类型转换。 我隐含地假设布尔值、数字等会自动转换为相应的 javascript 类型。 如果您认为这不在项目范围内,请关闭问题。

但是,自动转换会很好。 我只是花了大量时间调试由于错误值被检索为“false”并通过 javascript 的真值检查条件而引起的错误。

所有19条评论

我意识到 node-redis 不会对从 redis 检索到的字符串值进行任何数据类型转换。 我隐含地假设布尔值、数字等会自动转换为相应的 javascript 类型。 如果您认为这不在项目范围内,请关闭问题。

但是,自动转换会很好。 我只是花了大量时间调试由于错误值被检索为“false”并通过 javascript 的真值检查条件而引起的错误。

是的,真假也是让我着迷的那个。

我实际上想在库中解决这个问题,尽管肯定存在性能问题。

@brycebaril我们可以向 JSON.stringify/parse 输入引入一个标志。 这应该是一个很好的解决方案,你不这么认为吗?

也许在 createClient 构造函数中有一个选项。 就像是...
_parse_bool_:将“真”转换为真,将“假”转换为假
_parse_null_:将“空”转换为空

但是,您将如何处理“true”和“null”的实际字符串值? 无法检测原始输入类型是什么。

@Azmisov正如@dirkbonhomme指出的那样,这不是一个好的解决方案。 因此,仅使用 JSON.stringify/parse 可能是一种选择。

我想不是在特定的命令库上而是针对所有命令来解决这个问题。 这样也没有性能损失,因为无论如何我们都会检查每个参数,更重要的是:无论您如何传递参数(数组、对象、参数),它都能解决任何命令。

如果任何命令包含未定义或空值,我更愿意返回错误。 这几乎总是表明传递的参数有问题。
有些人可能希望有一种方法来处理不同的未定义和/或空值,所以我会添加一个选项,您可以将函数传递给该选项,如果任何命令包含空/未定义值,则会触发此函数。
该函数始终获取命令名称和传递给它的参数,并且返回值将替换原始参数。 这样,任何用户都可以根据需要处理这些值。
相同的逻辑可以应用于真/假。

@NodeRedis/贡献者@dirkbonhomme你怎么看? :)

@BridgeAR我不同意null是“有问题的迹象”。 采取这样的事情:

var myIndexes = ['one','two','three'], myMulti = client.multi();

myIndexes.forEach(function(aKey) { 
  myMulti.hget(aKey,'username'); 
  myMulti.hget(aKey,'address1');  
  myMulti.hget(aKey,'address2');
});

myMulti.exec(cb);

假设 'address2' 在您的数据中是可选的,那么null返回就可以了。

话虽如此,我认为这对许多人来说将是一个突破性的变化,所以像你提议的那样应该是可选的,而不是默认的。

@stockholmux我不确定我们是否谈论过同样的事情。 返回值不会以任何方式改变。

我想改变的是,使用null将导致字符串'null'代替:

client.set('foo', null);
client.get('foo', function (err, res) {
    console.log(res); // 'null'
});

我也不会破坏任何东西,因为我打算弃用旧行为(有些人可能会通过围绕问题构建来依赖破坏行为)并添加选项来立即自行处理此问题并从v.3.0.0 用于此类值。

“空”值问题是否得到解决?

你会在你的程序中定义一个特殊的标记来代表真正的空值吗? 当用户将某些东西设置为空时,您捕获该命令并将空值替换为您的特殊标记。当用户获得该东西时,您捕获该命令并将特殊标记替换为真正的空值给用户?

只是一个建议。 这个问题真的很困扰。 因为任何站点中的任何用户都可能有一个名为 'null' 的名称,所以您不希望将用户名解析为真正的 null 值;

“JSON.{parse,stringify} on input”标志是否有任何进展或决定? 自动完成此操作而不是在任何给定的获取/设置逻辑中会很好。

@taylorzane我现在没有时间,但它肯定计划实施。

听起来还不错。 如果我有一些时间可以尝试一下,那肯定会很好,而且我喜欢在我使用的模块源上进行黑客攻击。 :+1:

这现在有效吗?

我最终使用了一种不同的方法将数据序列化到 Redis 中,所以我从来没有考虑过实现这一点。

如果您不介意分享@taylorzane ,您将如何使用 Redis 将 JSON 对象存储在其内部可能具有空值的字段中

@slidenerd我正在展平 JSON 对象,然后在将其存储在 Redis 之前序列化每个展平的节点的值。 所以所有的值都是字符串。 即使有数千个值被反/序列化,它的性能也很好。

例子:

const a = {
  a: {
    b: {
      c: null,
      d: true,
      e: "hello"
    }
  }
}

const b = flatten(a)
console.log(b) /* =>
{
  '/a/b/c': null,
  '/a/b/d': true,
  '/a/b/e': 'hello'
}
*/

Object.entries(b).forEach(([key, value]) => {
  redis.set(key, JSON.stringify(value)) // or
  redis.hset('my_hash', key, JSON.stringify(value)) /*
  => "/a/b/c" -> "null"
  => "/a/b/d" -> "true"
  => "/a/b/e" -> "\"hello\""
  */
})

如果您需要更多指导,请随时通过 Gitter 或通过我个人资料中的电子邮件与我联系。

@slidenerd另一种选择是使用ReJSON来存储您的 JSON 对象——它通常是一个更好的选择,手动序列化所有内容,并且可以处理空值和未定义。 它是 Redis 模块,因此您必须有一个支持它的版本 (4.0+) 并将该模块安装到服务器中。 这超出了这个 Node.js 模块(和这个问题)的范围,但它解决了这个问题。

            items.push(JSON.stringify(object, (key, value) => {
                if (value === null || value === undefined) {
                    return undefined
                }
                else {
                    return isNaN(parseFloat(value)) ? value : parseFloat(value)
                }
            }))

谢谢@stockholmux我想出了一个更好的解决方案,而不使用外部依赖,这个想法是在 JSON.stringify 方法中使用替换函数,它恰好是第二个参数

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

abhaygarg picture abhaygarg  ·  5评论

lemon707 picture lemon707  ·  3评论

ghost picture ghost  ·  3评论

adamgajzlerowicz picture adamgajzlerowicz  ·  4评论

michaelwittig picture michaelwittig  ·  3评论