如何使用节点转换将一个对象转换为另一个对象

时间:2018-04-09 02:19:21

标签: javascript node.js typescript node-streams transform-stream

我是Node流的新手,并试图弄清楚为什么事情没有按预期工作。我只是在练习,想要做一个愚蠢的转变。

interface MyTransformStreamOptions {
  [key: string]: any
}

class MyTransformStream extends Transform {
  constructor(options) {
    options.readableObjectMode = true;
    options.writableObjectMode = true;

    super(options);
  }

  _transform(chunk, encoding, callback) {
    console.log('encoding: ' + encoding);

    // chunk should be an object here, due to
    // readableObjectMode = true right?

    const newObj = {};

    for (const [key, value] of Object.entries(chunk)) {
      console.log(`[key, value]: [${key}, ${value}]`);
      newObj['aa' + key] = 'bb' + value;
    }

    callback(null, newObj);
  }
}

const myTransformStream = new MyTransformStream({} as MyTransformStreamOptions);

process.stdin
  .pipe(myTransformStream)
  .pipe(process.stdout);

最后我运行脚本并通过stdin输入:

{ car: 'honda', truck: 'mazda' }

我也尝试过:

"{ car: 'honda', truck: 'mazda' }"

但循环将块视为字符串而不是对象。所以我看到输出如:

[key, value]: [0, 123]
[key, value]: [1, 32]
...etc...

我尝试了各种组合:

options.readableObjectMode = true/false;
options.writableObjectMode = true/false;

还在_transform()使用:

const obj = JSON.parse(chunk.toString());

但是obj永远不是一个对象,而且总是一个字符串。

我的目标是暗示将一个对象接收到我的变换流中,改变它并输出它。但是,即使使用JSON.parse(),我仍然无法处理字符串,即使我无法转换为对象。

我在哪里错了?

更新 - 部分解决方案

问题在于我使用JSON.parse()。我试图解析:

{ car: 'honda', truck: 'mazda' }

哪个是有效的JS,但不是有效的JSON,呃!

然而,更大的问题仍然存在。我已将变换流设置为:writableObjectMode = true,但是当我这样做时:

callback(null, newObj);

我收到错误:

TypeError: Invalid data, chunk must be a string or buffer, not object

如果我这样做:

callback(null, JSON.stringify(newObj));
事情按预期进行。

但是,鉴于我已经在对象模式下进行了设置,这不应该没有字符串化吗?

2 个答案:

答案 0 :(得分:0)

对象模式不会将流从缓冲区(它是缓冲区而不是字符串)转换为对象,它只是让数据类型为缓冲区或字符串以外的类型。您需要使用转换流将stdin缓冲区转换为对象,例如:

const ndjson = require('ndjson');

. . .

process.stdin
  .pipe(ndjson.parse())
  .pipe(myTransformStream)
  .pipe(process.stdout);

答案 1 :(得分:0)

因此,我的代码的主要问题是使用stdinstdout。它们是以字符串/缓冲模式运行的流。按原样使用它们,将stdin输送到流将以字符串/缓冲模式而不是对象模式进行管道传输。这同样适用于stdout。

我通过在对象模式下创建一个可读流来测试我的假设,该模型模拟了我通过_read()方法输入的stdin输入,然后让我的变换流将块转换为可读流输入到其中的对象

标准输出的管道仍然失败,因为它接受开箱即用的物品。我通过创建另一个转换流来确认这一点,该转换流只是通过JSON.stringify()将对象转换为字符串,然后stdout再次开心。

我遇到的所有问题'读/写对象模式'只是因为我在变换流的两边都有stdin和stdout。