使用地图或模板转换节点流中的JSON

时间:2015-05-14 15:45:36

标签: javascript json node.js stream request

我对Javascript和Node比较陌生,我喜欢边做边学,但是我对Javascript设计模式缺乏认识让我对尝试重新发明轮子很谨慎,我想知道社区,如果我想要做的事情已经以某种形式存在,我不是在寻找下面例子的具体代码,只是在正确的方向上轻推,我应该搜索什么。

我基本上想创建自己的私有IFTTT / Zapier,用于将数据从一个API插入另一个API。

我在一个API中使用节点模块requestGET数据,然后POST使用另一个API。

request支持流媒体做这样的整洁事情:

request.get('http://example.com/api')
  .pipe(request.put('http://example.com/api2'));

在这两个请求之间,我想通过转换来管道JSON,选择我需要的键/值对,并将键更改为目标API所期望的内容。

request.get('http://example.com/api')
  .pipe(apiToApi2Map)
  .pipe(request.put('http://example.com/api2'));

这是来自源API的JSON示例:http://pastebin.com/iKYTJCYk

这就是我要发送的内容:http://pastebin.com/133RhSJT

在这种情况下,转换后的JSON从每个对象的值中获取键"属性"键和每个对象的值"值"键。

所以我的问题:

  • 是否有框架,库或模块可以简化转换步骤?

  • 是否按照我应该接近的方式进行流式传输?这似乎是一种优雅的方式,因为我已经使用request创建了一些Javascript包装函数来轻松访问API方法,我只需要弄清楚中间步骤。

  • 是否可以创建"模板"或"地图"对于这些变换?假设我想要更改源API或目标API,最好创建一个新的文件,将源映射到所需的目标键/值。

希望社区能够提供帮助,我愿意接受任何建议! :) 这是我正在开发的一个开源项目,所以如果有人愿意参与进来,请与我们联系。

2 个答案:

答案 0 :(得分:5)

是的,你肯定是在正确的轨道上。我会指向您的两个流库,through可以更轻松地定义您自己的流,JSONStream有助于转换二进制流(就像您从request.get获得的那样)进入解析的JSON文档流。以下是使用这两个方法开始的示例:

var through = require('through');
var request = require('request');
var JSONStream = require('JSONStream');
var _ = require('underscore');

// Our function(doc) here will get called to handle each
// incoming document int he attributes array of the JSON stream
var transformer = through(function(doc) {
    var steps = _.findWhere(doc.items, {
        label: "Steps"
    });
    var activeMinutes = _.findWhere(doc.items, {
        label: "Active minutes"
    });
    var stepsGoal = _.findWhere(doc.items, {
        label: "Steps goal"
    });

    // Push the transformed document into the outgoing stream
    this.queue({
        steps: steps.value,
        activeMinutes: activeMinutes.value,
        stepsGoal: stepsGoal.value
    });
});

request
    .get('http://example.com/api')
    // The attributes.* here will split the JSON stream into chunks
    // where each chunk is an element of the array
    .pipe(JSONStream.parse('attributes.*'))
    .pipe(transformer)
    .pipe(request.put('http://example.com/api2'));

答案 1 :(得分:2)

正如安德鲁所指出的那样,通过或事件流,但我做了一些更容易使用的东西,scramjet。它的工作原理与之相同,但它的API与Arrays几乎完全相同,因此您可以轻松使用map和filter方法。

您的示例代码为:

person

我想这有点容易使用 - 但是在这个例子中你确实将数据累积到一个对象中 - 所以如果JSON实际上比这长得多,你可能想要再次将它变回JSONStream。 / p>