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

问题描述 投票:3回答:2

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

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

我正在使用节点模块request从一个API中获取GET数据,然后将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从每个对象“attribute”键的值和每个对象“value”键的值中获取键。

所以我的问题:

  • 是否有框架,库或模块可以使转换步骤更容易?
  • 流媒体的方式我应该接近这个?这似乎是一种优雅的方式,因为我用request创建了一些Javascript包装函数来轻松访问API方法,我只需要找出中间步骤。
  • 是否可以为这些变换创建“模板”或“地图”?假设我想要更改源API或目标API,那么创建一个将源映射到所需的目标键/值的新文件会很不错。

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

javascript json node.js stream request
2个回答
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'));

2
投票

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

您的示例的代码将是:

DataStream
   .pipeline(
       request.get('http://example.com/api'),
       JSONStream.parse('attributes.items.*')
   )
   .filter((item) => item.attibute)  // filter out ones without attribute
   .reduce((acc, item) => {
       acc[item.attribute] = item.value;
       return acc;
   .then((result) => request.put('http://example.com/api2', result))
;

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

© www.soinside.com 2019 - 2024. All rights reserved.