【问题标题】:How can I cleanly present well-formed names keys and values from JSON in JavaScript?如何在 JavaScript 中清晰地呈现来自 JSON 的格式良好的名称键和值?
【发布时间】:2019-06-14 04:53:16
【问题描述】:

我正在尝试向我的用户输出一些 JSON。 JSON 的格式可能会有所不同,JSON 的深度也可能有所不同。它可以是 1-5 层深的任何地方。

一些示例 JSON:

[
  {
    "name": "Previous DNS Records",
    "value": [
      {
        "host": "***.co.uk",
        "class": "IN",
        "ttl": 3573,
        "type": "TXT",
        "txt": "ANY obsoletedSee draft-ietf-dnsop-refuse-any",
        "entries": [
          "ANY obsoleted",
          "See draft-ietf-dnsop-refuse-any"
        ]
      }
    ]
  },
  {
    "name": "New DNS Records",
    "value": [
      {
        "host": "***.co.uk",
        "class": "IN",
        "ttl": 3516,
        "type": "TXT",
        "txt": "ANY obsoletedSee draft-ietf-dnsop-refuse-any",
        "entries": [
          "ANY obsoleted",
          "See draft-ietf-dnsop-refuse-any"
        ]
      }
    ]
  }
]

我需要循环显示键和值,并以某种形式向我的用户显示,无论是使用<table> 还是<dl>,键是名称和其中的值。

但是,因为我不知道 JSON 的深度或值是字符串还是 JSON 本身,所以这很棘手。也就是说,这是一个非常常见的用例,所以我想知道是否有一个库或内置的 JS 方法来帮助我,但我不知道。

【问题讨论】:

  • 看看 Vue。
  • 我实际上在使用 Vue。但这有什么帮助?
  • 这是一个非常常见的用例 - 具有未知模型定义、变量类型、长度和深度的数据模型不是常见用例。你没有编码问题,你有设计问题。
  • 这一切都取决于您想要的最终渲染。也许一个简单的 JS 库“JSON 查看器”或“JSON 格式化程序”就足够了。如果您必须进一步格式化数据,模板引擎会更有用(例如 Handlebars.js)。您将能够将对象的值转换为 HTML 元素,并为它们添加类和关联的 CSS。 handlebarsjs.com
  • 我们能看到当深度不同时事物的样子吗?通常你可以对每个值使用递归来检查它是真正的值还是对象,然后将其作为键值输出到 html 或做另一个包装器并重复故事

标签: javascript json


【解决方案1】:

您可以使用我的简单 JIterator IIFE 并玩转每个节点。还预定义了广度优先。
但 DepthFirst 似乎更适合这里:

function demoPrint() {
  var it = new JIterator(DemoJSON());
  do {
    var el = it.Current();
    if (el.HasOwnKey()) {
      if(el.HasStringValue()) {
        console.log("Level " + it.Level + " | " + el.key + '\t' + el.value);
      } else {
        console.log("Level " + it.Level + " | " + el.key + " ⤦");
      }
    } else if (el.HasStringValue()) {
      console.log("Level " + it.Level + " | " + el.value);
    }
  } while (it.DepthFirst());
}
function DemoJSON() {
  return [
  {
    "name": "Previous DNS Records",
    "value": [
      {
        "host": "***.co.uk",
        "class": "IN",
        "ttl": 3573,
        "type": "TXT",
        "txt": "ANY obsoletedSee draft-ietf-dnsop-refuse-any",
        "entries": [
          "ANY obsoleted",
          "See draft-ietf-dnsop-refuse-any"
        ]
      }
    ]
  },
  {
    "name": "New DNS Records",
    "value": [
      {
        "host": "***.co.uk",
        "class": "IN",
        "ttl": 3516,
        "type": "TXT",
        "txt": "ANY obsoletedSee draft-ietf-dnsop-refuse-any",
        "entries": [
          "ANY obsoleted",
          "See draft-ietf-dnsop-refuse-any"
        ]
      }
    ]
  }];
}

// https://github.com/eltomjan/ETEhomeTools/blob/master/HTM_HTA/JSON_Iterator_IIFE.js
'use strict';
var JNode = (function (jsNode) {

    function JNode(_parent, _pred, _key, _value) {
        this.parent = _parent;
        this.pred = _pred;
        this.node = null;
        this.next = null;
        this.key = _key;
        this.value = _value;
    }
    JNode.prototype.HasOwnKey = function () { return this.key && (typeof this.key != "number"); }
    JNode.prototype.HasStringValue = function () { return !(this.value instanceof Object); }

    return JNode;
})();

var JIterator = (function (json) {
    var root, current, maxLevel = -1;

    function JIterator(json, parent) {
        if (parent === undefined) parent = null;
        var pred = null, localCurrent;
        for (var child in json) {
            var obj = json[child] instanceof Object;
            if (json instanceof Array) child = parseInt(child); // non-associative array
            if (!root) root = localCurrent = new JNode(parent, null, child, json[child]);
            else {
                localCurrent = new JNode(parent, pred, child, obj ? ((json[child] instanceof Array) ? [] : {}) : json[child]);
            }
            if (pred) pred.next = localCurrent;
            if (parent && parent.node == null) parent.node = localCurrent;
            pred = localCurrent;
            if (obj) {
                var memPred = pred;
                JIterator(json[child], pred);
                pred = memPred;
            }
        }
        if (this) {
            current = root;
            this.Level = 0;
        }
    }

    JIterator.prototype.Current = function () { return current; }
    JIterator.prototype.SetCurrent = function (newCurrent) { current = newCurrent; }
    JIterator.prototype.Parent = function () {
        var retVal = current.parent;
        if (retVal == null) return false;
        this.Level--;
        return current = retVal;
    }
    JIterator.prototype.Pred = function () {
        var retVal = current.pred;
        if (retVal == null) return false;
        return current = retVal;
    }
    JIterator.prototype.Node = function () {
        var retVal = current.node;
        if (retVal == null) return false;
        this.Level++;
        return current = retVal;
    }
    JIterator.prototype.Next = function () {
        var retVal = current.next;
        if (retVal == null) return false;
        return current = retVal;
    }
    JIterator.prototype.Key = function () { return current.key; }
    JIterator.prototype.KeyDots = function () { return (typeof (current.key) == "number") ? "" : (current.key + ':'); }
    JIterator.prototype.Value = function () { return current.value; }
    JIterator.prototype.Reset = function () {
        current = root;
        this.Level = 0;
    }
    JIterator.prototype.RawPath = function () {
        var steps = [], level = current;
        do {
            if (level != null && level.value instanceof Object) {
                steps.push(level.key + (level.value instanceof Array ? "[]" : "{}"));
            } else {
                if (level != null) steps.push(level.key);
                else break;
            }
            level = level.parent;
        } while (level != null);
        var retVal = "";
        retVal = steps.reverse();
        return retVal;
    }
    JIterator.prototype.Path = function () {
        var steps = [], level = current;
        do {
            if (level != null && level.value instanceof Object) {
                var size = 0;
                var items = level.node;
                if (typeof (level.key) == "number") steps.push('[' + level.key + ']');
                else {
                    while (items) {
                        size++;
                        items = items.next;
                    }
                    var type = (level.value instanceof Array ? "[]" : "{}");
                    var prev = steps[steps.length - 1];
                    if (prev && prev[0] == '[') {
                        var last = prev.length - 1;
                        if (prev[last] == ']') {
                            last--;
                            if (!isNaN(prev.substr(1, last))) {
                                steps.pop();
                                size += '.' + prev.substr(1, last);
                            }
                        }
                    }
                    steps.push(level.key + type[0] + size + type[1]);
                }
            } else {
                if (level != null) {
                    if (typeof (level.key) == "number") steps.push('[' + level.key + ']');
                    else steps.push(level.key);
                }
                else break;
            }
            level = level.parent;
        } while (level != null);
        var retVal = "";
        retVal = steps.reverse();
        return retVal;
    }
    JIterator.prototype.DepthFirst = function () {
        if (current == null) return 0; // exit sign
        if (current.node != null) {
            current = current.node;
            this.Level++;
            if (maxLevel < this.Level) maxLevel = this.Level;
            return 1; // moved down
        } else if (current.next != null) {
            current = current.next;
            return 2; // moved right
        } else {
            while (current != null) {
                if (current.next != null) {
                    current = current.next;
                    return 3; // returned up & moved next
                }
                this.Level--;
                current = current.parent;
            }
        }
        return 0; // exit sign
    }
    JIterator.prototype.BreadthFirst = function () {
        if (current == null) return 0; // exit sign
        if (current.next) {
            current = current.next;
            return 1; // moved right
        } else if (current.parent) {
            var level = this.Level, point = current;
            while (this.DepthFirst() && level != this.Level);
            if (current) return 2; // returned up & moved next
            do {
                this.Reset();
                level++;
                while (this.DepthFirst() && level != this.Level);
                if (current) return 3; // returned up & moved next
            } while (maxLevel >= level);
            return current != null ? 3 : 0;
        } else if (current.node) {
            current = current.node;
            return 3;
        } else if (current.pred) {
            while (current.pred) current = current.pred;
            while (current && !current.node) current = current.next;
            if (!current) return null;
            else return this.DepthFirst();
        }
    }
    JIterator.prototype.ReadArray = function () {
        var retVal = {};
        var item = current;
        do {
            if (item.value instanceof Object) {
                if (item.value.length == 0) retVal[item.key] = item.node;
                else retVal[item.key] = item;
            } else retVal[item.key] = item.value;
            item = item.next;
        } while (item != null);
        return retVal;
    }
    JIterator.prototype.FindKey = function (key) {
        var pos = current;
        while (current && current.key != key) this.DepthFirst();
        if (current.key == key) {
            var retVal = current;
            current = pos;
            return retVal;
        } else {
            current = pos;
            return null;
        }
    }

    return JIterator;
})();

demoPrint();

【讨论】:

    猜你喜欢
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 2012-11-22
    • 1970-01-01
    • 2021-08-08
    • 2012-12-28
    • 1970-01-01
    相关资源
    最近更新 更多