javascript - 如何从元素获取 JSON 路径

标签 javascript json d3.js svg backbone.js

我已经实现了一个递归 JavaScript 函数,通过读取 JSON 模式在 svg 中绘制以下结构,如下所示。

有没有办法确定所选节点的 JSON 路径?例如,当用户单击节点(例如 country:string)时,有没有办法返回 JSON 路径(如 person.address.country)?

更新:我正在使用主干模型,因此我想到的解决方案是跟踪并将 JSON 路径添加为节点的属性以供以后使用。我正在寻找其他直接方法。

{
  "title": "person",
  "type": "object",
  "properties": {
    "first name": { "type": "string" },
    "last name": { "type": "string" },
    "age":{ "type":"number"},
    "birthday": { "type": "string", "format": "date-time" },
    "address": {
      "type": "object",
      "properties": {
        "street address": {
      "type": "object",
      "properties": {
        "house number": { "type": "number" },
        "lane": { "type": "string" }
      }    
    },
        "city": { "type": "string" },
        "state": { "type": "string" },
        "country": { "type" : "string" }
      }    
    },
    "phone number": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string"
          },
          "code": {
            "type": "number"
          }
        },
        "required": [
          "location",
          "code"
        ]
      }
    },
    "children": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "nickname":{"type":"string"}
  }
}

enter image description here

递归代码(主干函数)如下:

//initiate
  var title = data.title || "Root";
  var count = this.traverseJSONSchema(data, title, 0, 0, this.get('tempParent'));

//function
traverseJSONSchema: function (root, rootName, level, rank, resultPane) {
                    var height = this.nodeHeight,
                            width = this.containerWidth,
                            margin = width / 6,
                            x = 0,
                            overhead = rank * margin,
                            y = level * height;
                    var tempParent = resultPane.append("g").attr("class", "nested-group");
                    if (root.type === "object") {
                        if (rootName !== "") {
                            var nodeText = rootName + ":" + root.type;
                            var node = new DataMapper.Models.Node({parent: tempParent, text: nodeText, x: x, y: y, type: this.get('type'), category: "object", height: height, width: width});
                            node.drawContainerNode(overhead);
                            rank++;
                            level++;
                        }
                        var nestedParent = tempParent.append("g").attr("class", "nested-group");
                        var keys = root.properties; //select PROPERTIES
                        for (var i = 0; i < Object.keys(keys).length; i++) {   //traverse through each PROPERTY of the object
                            var keyName = Object.keys(keys)[i];
                            var key = keys[keyName];
                            level = this.traverseJSONSchema(key, keyName, level, rank, tempParent);
                        }

                    } else if (root.type === "array") {
                        var keys = root.items; //select ITEMS
                        if (rootName !== "") {
                            var nodeText = rootName + ":" + root.type + "[" + keys.type + "]";
                            var node = new DataMapper.Models.Node({parent: tempParent, text: nodeText, x: x, y: y, type: this.get('type'), category: "array", height: height, width: width});
                            node.drawContainerNode(overhead);
                            rank++;
                            level++;
                        }

                        level = this.traverseJSONSchema(keys, "", level, rank, tempParent); //recurse through the items of array
                    } else if (["string", "integer", "number", "boolean"].indexOf(root.type) > -1) {    //when the type is a primitive
                        tempParent.classed("nested-group", false);
                        if (rootName !== "") {
                            var nodeText = rootName + ":" + root.type;
                            var node = new DataMapper.Models.Node({parent: tempParent, text: nodeText, x: x, y: y, type: this.get('type'), category: root.type, height: height, width: width});
                            node.drawContainerNode(overhead);
                            rank++;
                            level++;
                        }
                    }
                    return level;
                }

最佳答案

您可以使用特殊处理来连接路径。

function getPath(object, search) {
    function iter(o, p) {
        return Object.keys(o).some(function (k) {
            if (k === key && o[k] && o[k].type === value) {
                path = p.concat(k).join('.');
                return true;
            }
            if (o[k] !== null && typeof o[k] === 'object') {
                return iter(o[k],
                    k === 'properties' && !o.title ?
                        p :
                        p.concat(k === 'properties' && o.title ? o.title : k)
                );
            }
        });
    }

    var parts = search.split(':'),
        key = parts[0],
        value = parts[1],
        path;

    iter(object, []);
    return path;
}

var data = { title: "person", type: "object", properties: { "first name": { type: "string" }, "last name": { type: "string" }, age: { type: "number" }, birthday: { type: "string", format: "date-time" }, address: { type: "object", properties: { "street address": { type: "object", properties: { "house number": { type: "number" }, lane: { type: "string" } } }, city: { type: "string" }, state: { type: "string" }, country: { type: "string" } } }, "phone number": { type: "array", items: { type: "object", properties: { location: { type: "string" }, code: { type: "number" } }, required: ["location", "code"] } }, children: { type: "array", items: { type: "string" } }, nickname: { type: "string" } } };

console.log(getPath(data, 'country:string'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

关于javascript - 如何从元素获取 JSON 路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39941691/

相关文章:

android - GCM XMPP 数据包中是否可能有非字符串值?

objective-c - 没有值的 AFNetworking JSON 数组

javascript - 在 D3.js 中旋转对象

javascript - 有序尺度行为

javascript - Bootstrap 导航栏下 zipper 接在 Safari 中不起作用

javascript - Converse 从 API 打开聊天

javascript - 将地址数组传递给 Geocode.geocoder() Google map

javascript - 使用像谷歌开发者工具这样的代码来跟踪 View ?

javascript - 使用 D3.js 的极坐标图

javascript - 访问时出现流错误,可能在真实检查后定义的函数表达式中键入