What is the best approach for converting between multi-level HTML lists with arbitrary depth and JSON?

I am looking for a way to convert between arbitrarily nested HTML lists and JSON. I have started with the MDN web component example expanding-list-web-component

Example nested list –

<ul is="expanding-list" id="expl">
    <li>UK
        <ul>
            <li>Yorkshire
                <ul>
                    <li>Leeds
                        <ul>
                            <li>Train station</li>
                            <li>Town hall</li>
                            <li>Headrow</li>
                        </ul>
                    </li>
                    <li>Bradford</li>
                    <li>Hull</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>USA
        <ul>
            <li>California
                <ul>
                    <li>Los Angeles</li>
                    <li>San Francisco</li>
                    <li>Berkeley</li>
                </ul>
            </li>
            <li>Nevada</li>
            <li>Oregon</li>
        </ul>
    </li>
</ul>

which could be expressed in the following JSON format-

{
  "UK": {
    "Yorkshire": {
      "Leeds": {
        "Train station": {},
        "Town hall": {},
        "Headrow": {}
      },
      "Bradford": {},
      "Hull": {}
    }
  },
  "USA": {
    "California": {
      "Los Angeles": {},
      "San Francisco": {},
      "Berkeley": {}
    },
    "Nevada": {},
    "Oregon": {}
  }
}

to extract the texts from the nested list, I tried –

const toJSON = async (elem) => {
  for (let i = 0; i < elem.childNodes.length; i += 1) {
    console.log('parentElement', elem.childNodes[i].parentElement);
    console.log('nodeType', elem.childNodes[i].nodeType);

    if (elem.childNodes[i].nodeType === 3) {
      // Node.TEXT_NODE (3) The actual Text inside an Element or Attr
      console.log('textContent', elem.childNodes[i].textContent);
    }
    toJSON(elem.childNodes[i]);
  }
};
toJSON(document.getElementById('expl'));

but this logs many newlines besides the text content and the parent child relationship is not obvious. I suspect my requirement is not uncommon and I am probably re-inventing the wheel. Is there a better approach to solving the problem?