JSFiddle - React, Tailwind, and code Playground

Object to UL tree;; click value to get the path to that value in the object with dot notation

by Travis Almand

HTML

<pre id="path">click a value to get the path...</pre>
<ul id="theme"></ul>

CSS

ul {
  list-style: none;
  margin: 0;
  padding: 0 20px;
}
span.value {
  color: blue;
  cursor: pointer;
}
pre {
  border: 1px solid black;
  padding: 10px;
}

JavaScript

console.clear();

let json = JSON.parse(`{
	"fiName": "fiName",
  "themes": {
  	"default": {
    	"themeName": "themeName",
      "header": {
      	"layout": "layout"
      },
      "footer-test": "footer",
      "test-test": {
      	"anotherTest": "test"
      }
    }
  }
}`);
let htmlString = '';

function createList(json){
  let htmlString = '';

  Object.keys(json).forEach(key => {
    if (typeof json[key] === 'object' && json[key] !== null) {
      htmlString += `<li><span class="key">${key}</span> : <ul>`;
      htmlString += createList(json[key]);
      htmlString += '</ul></li>';
    } else {
    	htmlString += `<li><span class="key">${key}</span> : <span class="value">${json[key]}</span></li>`;
    }
  });
  return htmlString;
}
htmlString += `${createList(json)}`;

document.querySelector('#theme').innerHTML = htmlString;

let pathString = '';
function buildPath(target) {
	let parent = target.parentElement;
  let key = parent.querySelector('.key');
  
  if (key && parent.nodeName === 'LI') {
    if (!key.innerText.includes('-')) {
	  	pathString += `${key.innerText}.`;
    } else {
    	pathString += `['${key.innerText}'].`;
    }
  }  
  
  if (parent.id !== 'theme') {
  	buildPath(parent);
  }
}

document.querySelectorAll('.value').forEach(value => {
	value.addEventListener('click', e => {
  	buildPath(e.target);
    path.innerText = 'json.' + pathString.split('.').reverse().join('.').substr(1).replace(/\.\[/, '[');
    pathString = '';
  });
});