<!DOCTYPE html> <html> <head> <title>JSON Viewer</title> <meta charset="UTF-8"> <!-- first import Vue --> <script src="https://unpkg.com/vue/dist/vue.js"></script> <!-- import JavaScript --> <script src="https://cdn.jsdelivr.net/npm/liquor-tree/dist/liquor-tree.umd.js"></script> </head> <body> <div id="app"> <liquor-json-viewer :json="json" /> </div> <template id="liquor-json-viewer"> <div class="json-viewer"> <tree :data="treeData" :options="treeOptions"> <span slot-scope="{ node }" class="viewer-item" :class="[node.data.type]"> <span v-if="node.hasChildren()" class="viewer-item__key"> {{ node.text }} <span v-if="node.collapsed()"> <template v-if="node.data.type == 'array'"> [ {{ node.children.length }} ] </template> <template v-else> { {{ node.children.length }} } </template> </span> </span> <span v-else class="viewer-item__prop"> <span class="viewer-item__key">{{ node.text }}</span> : <span class="viewer-item__value">{{ node.data.objectKey }}</span> </span> </span> </tree> </div> </template> <script> Vue.component('liquor-json-viewer', { template: '#liquor-json-viewer', props: ['json'], data() { return { treeData: this.parser(this.json), treeOptions: { } } }, methods: { isString(value) { return 'string' == typeof value }, isNaN(value) { return value !== value }, isBoolean(value) { return 'boolean' == typeof value }, isNumber(value) { return 'number' == typeof value }, isArray(value) { return Array.isArray(value) }, isValue(value) { return !this.isArray(value) && !this.isPlainObject(value) }, isPlainObject(value) { function isObject(obj) { return obj != null && typeof obj === 'object' && Array.isArray(obj) === false } if (!isObject(value) || !value.constructor || !value.constructor.prototype) { return false } return value.constructor.prototype.hasOwnProperty('isPrototypeOf') === true }, isIterable(value) { return this.isArray(value) || this.isPlainObject(value) }, map(obj, fn) { return Object.keys(obj).map((key) => { return fn(obj[key], key) }) }, transformObject(prop, key) { let obj = { text: key } if (this.isIterable(prop)) { obj.children = this.map(prop, this.transformObject) obj.data = { 'type': this.isArray(prop) ? 'array' : this.isPlainObject(prop) ? 'object' : 'unknown' } } else { obj.data = { 'objectKey': prop || `${prop}`, 'type': this.getType(prop) } } return obj }, getType(value) { if (this.isNaN(value)) { return 'viewer-type--nan' } if (this.isString(value)) { return 'viewer-type--string' } if (this.isNumber(value)) { return 'viewer-type--number' } if (this.isBoolean(value)) { return 'viewer-type--boolean' } if (null === value) { return 'viewer-type--null' } }, parser(obj) { return [{ text: 'JSONObject', state: { expanded: true }, data: {type: 'root'}, children: this.map(obj, this.transformObject) }] } } }) new Vue({ el: '#app', data: function() { return { json: { "object": { "a": "String", "b": [ 1, 2, 3 ], "c": 55, "e": false }, "array": [ 1, 2, 3, -4, -3, -2 ], "boolean": false, "null": null, "number": 21, "string": "Hi liquor-tree user!" } } } }) </script> </body> </html>
.viewer-item__key { color: #303030; } .viewer-item__key, .viewer-item__value { padding: 0 3px; } .viewer-type--boolean .viewer-item__value { color: #ff9b21; } .viewer-type--number .viewer-item__value { color: #f85441; } .viewer-type--null .viewer-item__value { color: #acabab; } .viewer-type--string .viewer-item__value { color: green; }