JSONify Dropdown Element Using Vanilla JavaScript

on in JavaScript Arrays & Objects
Last modified on

This function converts a regular <select> element both into an intented ul/li structure and JSON. It’s light and it’s been developed for a specific internal purpose. If you find it useful, with a small change, it also allows for exporting the option state (selected or not).


  • onclick convert select to indented ul/li including optgroup elements
  • onclick JSONify <select> to console.log() and it can further be passed to a Fetch event


See a live demo here.


The HTML structure builds a multiselect dropdown and an empty JSON container:

<div id="myselect">
    <select id="multiselect" name="languages[]" size="6" multiple>
        <optgroup label="More Cars">
            <option value="1">JavaScript</option>
            <option value="2">CSS</option>
            <option value="3">Script</option>
            <option value="4">Ruby</option>
            <option value="5">Go</option>
            <option value="6">PHP</option>
            <option value="7">.Com</option>
            <option value="8">Java</option>
        <optgroup label="Swedish Cars">
            <option value="volvo">Volvo</option>
            <option value="saab">Saab</option>
        <optgroup label="German Cars">
            <option value="mercedes">Mercedes</option>
            <option value="audi">Audi</option>
    <div id="json"></div>


function jsonifySelect(selectId) {
    const theSelect = document.getElementById('multiselect'),
          optgroups = theSelect.getElementsByTagName('optgroup');
    let myObj = {};

    for (let i = 0; i < optgroups.length; i++) {
        myObj[optgroups[i].getAttribute('label')] = [];
        let options = optgroups[i].getElementsByTagName('option');
        for (let j = 0; j < options.length; j++) {

    return myObj;

function recurse(data) {
    let result = '<ul>';

    for (let key in data) {
        if (typeof(data[key]) == 'object' && data[key] != null) {
            let x = key*1;

            if (isNaN(x)) {
                result += `<li>${key}<ul>`;
            result += recurse(data[key]);
            result += '</ul></li>';
        } else {
            result += (`<li data-value="${data[key]}">${data[key]}</li>'`);

    result += '</ul>';

    return result;

document.addEventListener('DOMContentLoaded', () => {
    document.getElementById('myselect').addEventListener('click', () => {

        let htmlStr = recurse(jsonifySelect('multiselect'));
        document.getElementById('json').innerHTML = htmlStr;

Note: In the jsonifySelect() function, inside the for (let j = 0; j < options.length; j++) { loop, check for options[j].selected to see if the option has been selected by the user.


// code here

for (let j = 0; j < options.length; j++) {
    myObj[optgroups[i].getAttribute('label')].push([options[j].innerHTML, options[j].selected]);

// more code here

In this case, I push an array containing the name of the item and the option state (boolean), true or false. This requires some changes to the ul/li structure, but if you’re not using and you’re only the JSON result, you should be good.

Related posts