我正在使用非常简单的Refify npm模块来处理循环结构JSON。它在Node.js中对循环结构JSON对象进行字符串化,然后发送给客户端。我的Angular前端接收字符串化的JSON,需要调用refify的parse方法将其转换回可用的对象。

如何在Angular前端中包含refify节点模块,以便可以引用refify?

后端用法如下所示:

var refify = require("refify");
app.get("/api/entries, function(req, res){
  var circularJSON = //a circular JSON object
  res.send(refify.stringify(circularJSON));
});


前端参考看起来像这样:

$http.get("/api/entries").success(function(data){
  $scope.entries = refify.parse(data);
});

最佳答案

这是Refify的分支版本,可以在node.js和浏览器中使用。

Forked Refify

您可以简单地下载index.js并将其包含在AngularJS应用程序中。并使用它。

看到下面的代码,我在片段和示例的最后添加了整个分叉的index.js文件。



(function(obj) {
  if (typeof exports === 'undefined') {
    obj.refify = refify;
  } else {
    module.exports = refify;
  }


  function refify(obj) {
    var objs = [];
    var paths = []

    var keyStack = [];
    var objStack = [];

    return walk(obj);

    function walk(it) {
      if (typeof it !== 'object') {
        return it;
      }
      objs.push(it);
      paths.push(keyStack.slice())
      objStack.push(it)
      var copy = initCopy(it);
      for (var k in it) {
        keyStack.push(k);
        var v = it[k];
        var i = objs.indexOf(v);
        if (i == -1) {
          copy[k] = walk(v)
        } else {
          var $ref = '#/' + paths[i].join('/');
          copy[k] = {
            $ref: $ref
          };
        }
        keyStack.pop();
      }
      objStack.pop();
      return copy;
    }
  }

  refify.parse = function(it) {
    if (typeof it !== 'object') it = JSON.parse(it);

    var keyStack = [];
    var copy = initCopy(it);

    walk(it);

    return copy;

    function walk(obj) {
      if (typeof obj !== 'object') {
        set(copy, keyStack.slice(), obj);
        return;
      }
      for (var k in obj) {
        keyStack.push(k);
        var current = obj[k];
        var objPath = parseRef(current);
        while (objPath) {
          current = get(copy, objPath);
          objPath = parseRef(current);
        }
        if (current === obj[k]) {
          // We did *not* follow a reference
          set(copy, keyStack.slice(), initCopy(current));
          walk(current);
        } else {
          // We *did* follow a reference
          set(copy, keyStack.slice(), current);
        }
        keyStack.pop();
      }
    }
  }

  refify.stringify = function(obj, replacer, spaces) {
    return JSON.stringify(refify(obj), replacer, spaces)
  }

  function parseRef(value) {
    if (typeof value !== 'object') return false;
    if (!value.$ref) return false;
    var path = value.$ref == '#/' ? [] : value.$ref.split('/').slice(1);
    return path
  }

  function get(obj, path) {
    if (!path.length) return obj;
    if (typeof obj !== 'object') return;
    var next = obj[path.shift()];
    return get(next, path);
  }

  refify.set = set;

  function set(obj, path, value) {
    if (path.length === 0) throw new Error("Cannot replace root object");
    var key = path.shift();
    if (!path.length) {
      obj[key] = value;
      return;
    }
    switch (typeof obj[key]) {
      case 'undefined':
        obj[key] = isNaN(parseInt(key, 10)) ? {} : [];
        break;
      case 'object':
        break;
      default:
        throw new Error("Tried to set property " + key + " of non-object " + obj[key]);
    }
    set(obj[key], path, value);
  }

  function initCopy(obj) {
    if (typeof obj !== 'object') return obj;
    return Array.isArray(obj) ? [] : {}
  }

}(this));


// Example with forked version

var obj = {
  inside: {
    name: 'Stackoverflow',
    id: '98776'
  }
};

obj.inside.parent = obj;

var refifyObject= refify(obj);

document.getElementById("out").innerHTML = JSON.stringify(refifyObject);

<div id="out"></div>

10-08 16:34