Home > database >  Load nested JSON Data into HTML <UL> <LI> list....>
Load nested JSON Data into HTML <UL> <LI> list....>

Time:01-01

To start with, the environment:

  • node js
  • express
  • mySQL
  • plain old Javascript (no frameworks used)

I'm reading a List of F1 Circuits by Country from a MySQL Database, getting the output in JSON and I would like to load the data into an HTML Page using javascript on the client side, this being the desired format:

  • Country:
    • Race Track Name
    • Race Track 2 Name
  • Country 2:
    • Race Track Name
  • Country 3: [Dont show anything if no track exists]

Some Countries do not have a track at all, some have 1 race track, and other countries have seceral race tracks as shown in this JSON output from my SQL Query: JSON Output

As shown in the pic, Country at Index 0 has no track, Country at Index 10 has 1 track, Country at Index 14 has more than 1 track.

Im stuck at the point to read that JSON Data into a loop and load it into the page in the appropriate <LI> elements to display as shown above (including the nesting).

The problem I have is I cant make sense of how to read this JSON format as it is not in the normal format that I receive it from my other queries. I get all this extra "Country:" tag at the start of each line and the actual data is full of \ so I dont know how to read it. I tried .stringify, I tried .parse but cant just extract the country name or track name in a variable.

I have the following eventlistener and function defined:

// Add an event listener to load the sidebar with the list of F1 Circuits once the DOM has completed loading
document.addEventListener('DOMContentLoaded', function () {
    fetch('http://192.168.68.102:3000/loadF1Circuits')
    .then(response => response.json())
    .then(responseData => loadCircuits(responseData['data']));
  });


  
  function loadCircuits(circuitsList) {
    const circuitsUL_List = document.querySelector("#circuits");
    let htmlToLoad = "";

    for (const racingEvent of circuitsList) {
  
    }
    circuitsUL_List.innerHTML=htmlToLoad;
  }

and this is my SQL query in order to get the data nested by country:

    async getAllCircuitsByCountry() {
        try {
            const response = await new Promise((resolve, reject) => {
                const query = 
                `
                select  json_object (
                            'Country', Countries.cnt_name,
                            'circuits', (select cast(concat('[', GROUP_CONCAT(json_object('Circuits_ID', Circuits.crt_ID, 'Circuit_name', Circuits.crt_name)),']')  as JSON) 
                                        FROM    Circuits 
                                        WHERE   Countries.cnt_name = Circuits.crt_country_name)) 
                            as Country 
                FROM    Countries
                ORDER BY Countries.cnt_name;`;

                connection.query(query, (err, results) => {
                    if (err) reject(new Error(err.message));
                    resolve(results);
                })
            });
            return response;
        } catch (error) {
            console.log(error);
        };
    };

This is the JSON Data I get in answer to the comment below, there the array has 264 objects so quite long, which is why I didnt paste the whole output in the first place but showed a screen shot at the top instead:

{"data":[{"Country":"{\"Country\": \"Afghanistan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Aland Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Albania\", \"circuits\": null}"},{"Country":"{\"Country\": \"Algeria\", \"circuits\": null}"},{"Country":"{\"Country\": \"American Samoa\", \"circuits\": null}"},{"Country":"{\"Country\": \"Andorra\", \"circuits\": null}"},{"Country":"{\"Country\": \"Angola\", \"circuits\": null}"},{"Country":"{\"Country\": \"Anguilla\", \"circuits\": null}"},{"Country":"{\"Country\": \"Antarctica\", \"circuits\": null}"},{"Country":"{\"Country\": \"Antigua and Barbuda\", \"circuits\": null}"},{"Country":"{\"Country\": \"Argentina\", \"circuits\": [{\"Circuits_ID\": 25, \"Circuit_name\": \"Autódromo Juan y Oscar Gálvez\"}]}"},{"Country":"{\"Country\": \"Armenia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Aruba\", \"circuits\": null}"},{"Country":"{\"Country\": \"Ascension Island\", \"circuits\": null}"},{"Country":"{\"Country\": \"Australia\", \"circuits\": [{\"Circuits_ID\": 1, \"Circuit_name\": \"Albert Park Grand Prix Circuit\"}, {\"Circuits_ID\": 29, \"Circuit_name\": \"Adelaide Street Circuit\"}]}"},{"Country":"{\"Country\": \"Austria\", \"circuits\": [{\"Circuits_ID\": 23, \"Circuit_name\": \"A1-Ring\"}, {\"Circuits_ID\": 57, \"Circuit_name\": \"Zeltweg\"}, {\"Circuits_ID\": 70, \"Circuit_name\": \"Red Bull Ring\"}]}"},{"Country":"{\"Country\": \"Azerbaijan\", \"circuits\": [{\"Circuits_ID\": 73, \"Circuit_name\": \"Baku City Circuit\"}]}"},{"Country":"{\"Country\": \"Bahamas\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bahrain\", \"circuits\": [{\"Circuits_ID\": 3, \"Circuit_name\": \"Bahrain International Circuit\"}]}"}"}]}

By changing my SQL Query as follows:

                SELECT      Countries.cnt_name, Circuits.crt_name
                FROM        Countries
                LEFT JOIN   Circuits
                ON          Countries.cnt_name = Circuits.crt_country_name
                ORDER BY    Countries.cnt_name;`;
I get a different JSON format but then I get several objects for the same Country if a country has more than once track, as per this JSON Output:

{"data":[{"cnt_name":"Afghanistan","crt_name":null},{"cnt_name":"Aland Islands","crt_name":null},{"cnt_name":"Albania","crt_name":null},{"cnt_name":"Algeria","crt_name":null},{"cnt_name":"American Samoa","crt_name":null},{"cnt_name":"Andorra","crt_name":null},{"cnt_name":"Angola","crt_name":null},{"cnt_name":"Anguilla","crt_name":null},{"cnt_name":"Antarctica","crt_name":null},{"cnt_name":"Antigua and Barbuda","crt_name":null},{"cnt_name":"Argentina","crt_name":"Autódromo Juan y Oscar Gálvez"},{"cnt_name":"Armenia","crt_name":null},{"cnt_name":"Aruba","crt_name":null},{"cnt_name":"Ascension Island","crt_name":null},{"cnt_name":"Australia","crt_name":"Albert Park Grand Prix Circuit"},{"cnt_name":"Australia","crt_name":"Adelaide Street Circuit"},{"cnt_name":"Austria","crt_name":"A1-Ring"},{"cnt_name":"Austria","crt_name":"Zeltweg"},{"cnt_name":"Austria","crt_name":"Red Bull Ring"},{"cnt_name":"Azerbaijan","crt_name":"Baku City Circuit"},{"cnt_name":"Bahamas","crt_name":null},{"cnt_name":"Bahrain","crt_name":"Bahrain International Circuit"}

Could someone point me in the right direction please on how to read the data from that JSON output.

Thank you in advance. M.

CodePudding user response:

Here is my version using template literals

You can improve this by returning a proper JSON data instead of nested JSON strings.

I could bypass it by replacing all sorts of stuff

Remove the first two lines when you have fixed the JSON on the server

jsonString = jsonString.replaceAll(/\\/g,"").replaceAll(/"{/g,"{").replaceAll(/}"}/g,"}}")
const circuitsList = JSON.parse(jsonString).data;
document.getElementById("circuits").innerHTML = circuitsList.map(({Country}) => {
  const [country, circuits] = Object.values(Country);
  const circuitUl = circuits && circuits.length ?  `<ul>${circuits.map(circuit=>`<li>${circuit.Circuit_name}</li>`).join('')}</ul>` : '';
  return `<li>${country} ${circuitUl}</li>`
  }).join("");
<ul id="circuits"></ul>
<script>let jsonString = `{"data":[{"Country":"{\"Country\": \"Afghanistan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Aland Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Albania\", \"circuits\": null}"},{"Country":"{\"Country\": \"Algeria\", \"circuits\": null}"},{"Country":"{\"Country\": \"American Samoa\", \"circuits\": null}"},{"Country":"{\"Country\": \"Andorra\", \"circuits\": null}"},{"Country":"{\"Country\": \"Angola\", \"circuits\": null}"},{"Country":"{\"Country\": \"Anguilla\", \"circuits\": null}"},{"Country":"{\"Country\": \"Antarctica\", \"circuits\": null}"},{"Country":"{\"Country\": \"Antigua and Barbuda\", \"circuits\": null}"},{"Country":"{\"Country\": \"Argentina\", \"circuits\": [{\"Circuits_ID\": 25, \"Circuit_name\": \"Autódromo Juan y Oscar Gálvez\"}]}"},{"Country":"{\"Country\": \"Armenia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Aruba\", \"circuits\": null}"},{"Country":"{\"Country\": \"Ascension Island\", \"circuits\": null}"},{"Country":"{\"Country\": \"Australia\", \"circuits\": [{\"Circuits_ID\": 1, \"Circuit_name\": \"Albert Park Grand Prix Circuit\"}, {\"Circuits_ID\": 29, \"Circuit_name\": \"Adelaide Street Circuit\"}]}"},{"Country":"{\"Country\": \"Austria\", \"circuits\": [{\"Circuits_ID\": 23, \"Circuit_name\": \"A1-Ring\"}, {\"Circuits_ID\": 57, \"Circuit_name\": \"Zeltweg\"}, {\"Circuits_ID\": 70, \"Circuit_name\": \"Red Bull Ring\"}]}"},{"Country":"{\"Country\": \"Azerbaijan\", \"circuits\": [{\"Circuits_ID\": 73, \"Circuit_name\": \"Baku City Circuit\"}]}"},{"Country":"{\"Country\": \"Bahamas\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bahrain\", \"circuits\": [{\"Circuits_ID\": 3, \"Circuit_name\": \"Bahrain International Circuit\"}]}"},{"Country":"{\"Country\": \"Bangladesh\", \"circuits\": null}"},{"Country":"{\"Country\": \"Barbados\", \"circuits\": null}"},{"Country":"{\"Country\": \"Belarus\", \"circuits\": null}"},{"Country":"{\"Country\": \"Belgium\", \"circuits\": [{\"Circuits_ID\": 13, \"Circuit_name\": \"Circuit de Spa-Francorchamps\"}, {\"Circuits_ID\": 40, \"Circuit_name\": \"Zolder\"}, {\"Circuits_ID\": 50, \"Circuit_name\": \"Nivelles-Baulers\"}]}"},{"Country":"{\"Country\": \"Belize\", \"circuits\": null}"},{"Country":"{\"Country\": \"Benin\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bermuda\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bhutan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bolivia (Plurinational State of)\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bonaire, Sint Eustatius and Saba\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bosnia and Herzegovina\", \"circuits\": null}"},{"Country":"{\"Country\": \"Botswana\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bouvet Island\", \"circuits\": null}"},{"Country":"{\"Country\": \"Brazil\", \"circuits\": [{\"Circuits_ID\": 18, \"Circuit_name\": \"Autódromo José Carlos Pace\"}, {\"Circuits_ID\": 36, \"Circuit_name\": \"Autódromo Internacional Nelson Piquet\"}]}"},{"Country":"{\"Country\": \"British Indian Ocean Territory\", \"circuits\": null}"},{"Country":"{\"Country\": \"Brunei Darussalam\", \"circuits\": null}"},{"Country":"{\"Country\": \"Bulgaria\", \"circuits\": null}"},{"Country":"{\"Country\": \"Burkina Faso\", \"circuits\": null}"},{"Country":"{\"Country\": \"Burundi\", \"circuits\": null}"},{"Country":"{\"Country\": \"Cabo Verde\", \"circuits\": null}"},{"Country":"{\"Country\": \"Cambodia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Cameroon\", \"circuits\": null}"},{"Country":"{\"Country\": \"Canada\", \"circuits\": [{\"Circuits_ID\": 7, \"Circuit_name\": \"Circuit Gilles Villeneuve\"}, {\"Circuits_ID\": 48, \"Circuit_name\": \"Mosport International Raceway\"}, {\"Circuits_ID\": 52, \"Circuit_name\": \"Circuit Mont-Tremblant\"}]}"},{"Country":"{\"Country\": \"Canary Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Catalonia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Cayman Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Central African Republic\", \"circuits\": null}"},{"Country":"{\"Country\": \"Ceuta & Melilla\", \"circuits\": null}"},{"Country":"{\"Country\": \"Chad\", \"circuits\": null}"},{"Country":"{\"Country\": \"Chile\", \"circuits\": null}"},{"Country":"{\"Country\": \"China\", \"circuits\": [{\"Circuits_ID\": 17, \"Circuit_name\": \"Shanghai International Circuit\"}]}"},{"Country":"{\"Country\": \"Christmas Island\", \"circuits\": null}"},{"Country":"{\"Country\": \"Clipperton Island\", \"circuits\": null}"},{"Country":"{\"Country\": \"Cocos (Keeling) Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Colombia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Comoros\", \"circuits\": null}"},{"Country":"{\"Country\": \"Cook Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Costa Rica\", \"circuits\": null}"},{"Country":"{\"Country\": \"Côte d'Ivoire\", \"circuits\": null}"},{"Country":"{\"Country\": \"Croatia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Cuba\", \"circuits\": null}"},{"Country":"{\"Country\": \"Curaçao\", \"circuits\": null}"},{"Country":"{\"Country\": \"Cyprus\", \"circuits\": null}"},{"Country":"{\"Country\": \"Czech Republic\", \"circuits\": null}"},{"Country":"{\"Country\": \"Democratic Republic of the Congo\", \"circuits\": null}"},{"Country":"{\"Country\": \"Denmark\", \"circuits\": null}"},{"Country":"{\"Country\": \"Diego Garcia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Djibouti\", \"circuits\": null}"},{"Country":"{\"Country\": \"Dominica\", \"circuits\": null}"},{"Country":"{\"Country\": \"Dominican Republic\", \"circuits\": null}"},{"Country":"{\"Country\": \"Ecuador\", \"circuits\": null}"},{"Country":"{\"Country\": \"Egypt\", \"circuits\": null}"},{"Country":"{\"Country\": \"El Salvador\", \"circuits\": null}"},{"Country":"{\"Country\": \"England\", \"circuits\": null}"},{"Country":"{\"Country\": \"Equatorial Guinea\", \"circuits\": null}"},{"Country":"{\"Country\": \"Eritrea\", \"circuits\": null}"},{"Country":"{\"Country\": \"Estonia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Ethiopia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Europe\", \"circuits\": null}"},{"Country":"{\"Country\": \"Falkland Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Faroe Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Federated States of Micronesia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Fiji\", \"circuits\": null}"},{"Country":"{\"Country\": \"Finland\", \"circuits\": null}"},{"Country":"{\"Country\": \"France\", \"circuits\": [{\"Circuits_ID\": 8, \"Circuit_name\": \"Circuit de Nevers Magny-Cours\"}, {\"Circuits_ID\": 34, \"Circuit_name\": \"Circuit Paul Ricard\"}, {\"Circuits_ID\": 41, \"Circuit_name\": \"Dijon-Prenois\"}, {\"Circuits_ID\": 51, \"Circuit_name\": \"Charade Circuit\"}, {\"Circuits_ID\": 53, \"Circuit_name\": \"Rouen-Les-Essarts\"}, {\"Circuits_ID\": 54, \"Circuit_name\": \"Le Mans\"}, {\"Circuits_ID\": 55, \"Circuit_name\": \"Reims-Gueux\"}]}"},{"Country":"{\"Country\": \"French Guiana\", \"circuits\": null}"},{"Country":"{\"Country\": \"French Polynesia\", \"circuits\": null}"},{"Country":"{\"Country\": \"French Southern Territories\", \"circuits\": null}"},{"Country":"{\"Country\": \"Gabon\", \"circuits\": null}"},{"Country":"{\"Country\": \"Galicia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Gambia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Georgia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Germany\", \"circuits\": [{\"Circuits_ID\": 10, \"Circuit_name\": \"Hockenheimring\"}, {\"Circuits_ID\": 20, \"Circuit_name\": \"Nürburgring\"}, {\"Circuits_ID\": 61, \"Circuit_name\": \"AVUS\"}]}"},{"Country":"{\"Country\": \"Ghana\", \"circuits\": null}"},{"Country":"{\"Country\": \"Gibraltar\", \"circuits\": null}"},{"Country":"{\"Country\": \"Greece\", \"circuits\": null}"},{"Country":"{\"Country\": \"Greenland\", \"circuits\": null}"},{"Country":"{\"Country\": \"Grenada\", \"circuits\": null}"},{"Country":"{\"Country\": \"Guadeloupe\", \"circuits\": null}"},{"Country":"{\"Country\": \"Guam\", \"circuits\": null}"},{"Country":"{\"Country\": \"Guatemala\", \"circuits\": null}"},{"Country":"{\"Country\": \"Guernsey\", \"circuits\": null}"},{"Country":"{\"Country\": \"Guinea\", \"circuits\": null}"},{"Country":"{\"Country\": \"Guinea-Bissau\", \"circuits\": null}"},{"Country":"{\"Country\": \"Guyana\", \"circuits\": null}"},{"Country":"{\"Country\": \"Haiti\", \"circuits\": null}"},{"Country":"{\"Country\": \"Heard Island and McDonald Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Holy See\", \"circuits\": null}"},{"Country":"{\"Country\": \"Honduras\", \"circuits\": null}"},{"Country":"{\"Country\": \"Hong Kong\", \"circuits\": null}"},{"Country":"{\"Country\": \"Hungary\", \"circuits\": [{\"Circuits_ID\": 11, \"Circuit_name\": \"Hungaroring\"}]}"},{"Country":"{\"Country\": \"Iceland\", \"circuits\": null}"},{"Country":"{\"Country\": \"India\", \"circuits\": [{\"Circuits_ID\": 68, \"Circuit_name\": \"Buddh International Circuit\"}]}"},{"Country":"{\"Country\": \"Indonesia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Iran (Islamic Republic of)\", \"circuits\": null}"},{"Country":"{\"Country\": \"Iraq\", \"circuits\": null}"},{"Country":"{\"Country\": \"Ireland\", \"circuits\": null}"},{"Country":"{\"Country\": \"Isle of Man\", \"circuits\": null}"},{"Country":"{\"Country\": \"Israel\", \"circuits\": null}"},{"Country":"{\"Country\": \"Italy\", \"circuits\": [{\"Circuits_ID\": 14, \"Circuit_name\": \"Autodromo Nazionale di Monza\"}, {\"Circuits_ID\": 21, \"Circuit_name\": \"Autodromo Enzo e Dino Ferrari\"}, {\"Circuits_ID\": 65, \"Circuit_name\": \"Pescara Circuit\"}, {\"Circuits_ID\": 76, \"Circuit_name\": \"Autodromo Internazionale del Mugello\"}]}"},{"Country":"{\"Country\": \"Jamaica\", \"circuits\": null}"},{"Country":"{\"Country\": \"Japan\", \"circuits\": [{\"Circuits_ID\": 16, \"Circuit_name\": \"Fuji Speedway\"}, {\"Circuits_ID\": 22, \"Circuit_name\": \"Suzuka Circuit\"}, {\"Circuits_ID\": 28, \"Circuit_name\": \"Okayama International Circuit\"}]}"},{"Country":"{\"Country\": \"Jersey\", \"circuits\": null}"},{"Country":"{\"Country\": \"Jordan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Kazakhstan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Kenya\", \"circuits\": null}"},{"Country":"{\"Country\": \"Kiribati\", \"circuits\": null}"},{"Country":"{\"Country\": \"Kosovo\", \"circuits\": null}"},{"Country":"{\"Country\": \"Kuwait\", \"circuits\": null}"},{"Country":"{\"Country\": \"Kyrgyzstan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Laos\", \"circuits\": null}"},{"Country":"{\"Country\": \"Latvia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Lebanon\", \"circuits\": null}"},{"Country":"{\"Country\": \"Lesotho\", \"circuits\": null}"},{"Country":"{\"Country\": \"Liberia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Libya\", \"circuits\": null}"},{"Country":"{\"Country\": \"Liechtenstein\", \"circuits\": null}"},{"Country":"{\"Country\": \"Lithuania\", \"circuits\": null}"},{"Country":"{\"Country\": \"Luxembourg\", \"circuits\": null}"},{"Country":"{\"Country\": \"Macau\", \"circuits\": null}"},{"Country":"{\"Country\": \"Madagascar\", \"circuits\": null}"},{"Country":"{\"Country\": \"Malawi\", \"circuits\": null}"},{"Country":"{\"Country\": \"Malaysia\", \"circuits\": [{\"Circuits_ID\": 2, \"Circuit_name\": \"Sepang International Circuit\"}]}"},{"Country":"{\"Country\": \"Maldives\", \"circuits\": null}"},{"Country":"{\"Country\": \"Mali\", \"circuits\": null}"},{"Country":"{\"Country\": \"Malta\", \"circuits\": null}"},{"Country":"{\"Country\": \"Marshall Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Martinique\", \"circuits\": null}"},{"Country":"{\"Country\": \"Mauritania\", \"circuits\": null}"},{"Country":"{\"Country\": \"Mauritius\", \"circuits\": null}"},{"Country":"{\"Country\": \"Mayotte\", \"circuits\": null}"},{"Country":"{\"Country\": \"Mexico\", \"circuits\": [{\"Circuits_ID\": 32, \"Circuit_name\": \"Autódromo Hermanos Rodríguez\"}]}"},{"Country":"{\"Country\": \"Moldova\", \"circuits\": null}"},{"Country":"{\"Country\": \"Monaco\", \"circuits\": [{\"Circuits_ID\": 6, \"Circuit_name\": \"Circuit de Monaco\"}]}"},{"Country":"{\"Country\": \"Mongolia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Montenegro\", \"circuits\": null}"},{"Country":"{\"Country\": \"Montserrat\", \"circuits\": null}"},{"Country":"{\"Country\": \"Morocco\", \"circuits\": [{\"Circuits_ID\": 64, \"Circuit_name\": \"Ain Diab\"}]}"},{"Country":"{\"Country\": \"Mozambique\", \"circuits\": null}"},{"Country":"{\"Country\": \"Myanmar\", \"circuits\": null}"},{"Country":"{\"Country\": \"Namibia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Nauru\", \"circuits\": null}"},{"Country":"{\"Country\": \"Nepal\", \"circuits\": null}"},{"Country":"{\"Country\": \"Netherlands\", \"circuits\": [{\"Circuits_ID\": 39, \"Circuit_name\": \"Circuit Park Zandvoort\"}]}"},{"Country":"{\"Country\": \"New Caledonia\", \"circuits\": null}"},{"Country":"{\"Country\": \"New Zealand\", \"circuits\": null}"},{"Country":"{\"Country\": \"Nicaragua\", \"circuits\": null}"},{"Country":"{\"Country\": \"Niger\", \"circuits\": null}"},{"Country":"{\"Country\": \"Nigeria\", \"circuits\": null}"},{"Country":"{\"Country\": \"Niue\", \"circuits\": null}"},{"Country":"{\"Country\": \"Norfolk Island\", \"circuits\": null}"},{"Country":"{\"Country\": \"North Korea\", \"circuits\": null}"},{"Country":"{\"Country\": \"North Macedonia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Northern Ireland\", \"circuits\": null}"},{"Country":"{\"Country\": \"Northern Mariana Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Norway\", \"circuits\": null}"},{"Country":"{\"Country\": \"Oman\", \"circuits\": null}"},{"Country":"{\"Country\": \"Pakistan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Palau\", \"circuits\": null}"},{"Country":"{\"Country\": \"Panama\", \"circuits\": null}"},{"Country":"{\"Country\": \"Papua New Guinea\", \"circuits\": null}"},{"Country":"{\"Country\": \"Paraguay\", \"circuits\": null}"},{"Country":"{\"Country\": \"Peru\", \"circuits\": null}"},{"Country":"{\"Country\": \"Philippines\", \"circuits\": null}"},{"Country":"{\"Country\": \"Pitcairn\", \"circuits\": null}"},{"Country":"{\"Country\": \"Poland\", \"circuits\": null}"},{"Country":"{\"Country\": \"Portugal\", \"circuits\": [{\"Circuits_ID\": 27, \"Circuit_name\": \"Autódromo do Estoril\"}, {\"Circuits_ID\": 59, \"Circuit_name\": \"Circuito da Boavista\"}, {\"Circuits_ID\": 62, \"Circuit_name\": \"Monsanto Park Circuit\"}, {\"Circuits_ID\": 75, \"Circuit_name\": \"Autódromo Internacional do Algarve\"}]}"},{"Country":"{\"Country\": \"Puerto Rico\", \"circuits\": null}"},{"Country":"{\"Country\": \"Qatar\", \"circuits\": [{\"Circuits_ID\": 78, \"Circuit_name\": \"Losail International Circuit\"}]}"},{"Country":"{\"Country\": \"Republic of the Congo\", \"circuits\": null}"},{"Country":"{\"Country\": \"Réunion\", \"circuits\": null}"},{"Country":"{\"Country\": \"Romania\", \"circuits\": null}"},{"Country":"{\"Country\": \"Russia\", \"circuits\": [{\"Circuits_ID\": 71, \"Circuit_name\": \"Sochi Autodrom\"}]}"},{"Country":"{\"Country\": \"Rwanda\", \"circuits\": null}"},{"Country":"{\"Country\": \"Saint Barthélemy\", \"circuits\": null}"},{"Country":"{\"Country\": \"Saint Helena, Ascension and Tristan da Cunha\", \"circuits\": null}"},{"Country":"{\"Country\": \"Saint Kitts and Nevis\", \"circuits\": null}"},{"Country":"{\"Country\": \"Saint Lucia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Saint Martin\", \"circuits\": null}"},{"Country":"{\"Country\": \"Saint Pierre and Miquelon\", \"circuits\": null}"},{"Country":"{\"Country\": \"Saint Vincent and the Grenadines\", \"circuits\": null}"},{"Country":"{\"Country\": \"Samoa\", \"circuits\": null}"},{"Country":"{\"Country\": \"San Marino\", \"circuits\": null}"},{"Country":"{\"Country\": \"Sao Tome and Principe\", \"circuits\": null}"},{"Country":"{\"Country\": \"Saudi Arabia\", \"circuits\": [{\"Circuits_ID\": 77, \"Circuit_name\": \"Jeddah Street Circuit\"}]}"},{"Country":"{\"Country\": \"Scotland\", \"circuits\": null}"},{"Country":"{\"Country\": \"Senegal\", \"circuits\": null}"},{"Country":"{\"Country\": \"Serbia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Seychelles\", \"circuits\": null}"},{"Country":"{\"Country\": \"Sierra Leone\", \"circuits\": null}"},{"Country":"{\"Country\": \"Singapore\", \"circuits\": [{\"Circuits_ID\": 15, \"Circuit_name\": \"Marina Bay Street Circuit\"}]}"},{"Country":"{\"Country\": \"Sint Maarten\", \"circuits\": null}"},{"Country":"{\"Country\": \"Slovakia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Slovenia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Solomon Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Somalia\", \"circuits\": null}"},{"Country":"{\"Country\": \"South Africa\", \"circuits\": [{\"Circuits_ID\": 30, \"Circuit_name\": \"Kyalami\"}, {\"Circuits_ID\": 56, \"Circuit_name\": \"Prince George Circuit\"}]}"},{"Country":"{\"Country\": \"South Georgia and the South Sandwich Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"South Korea\", \"circuits\": null}"},{"Country":"{\"Country\": \"South Sudan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Spain\", \"circuits\": [{\"Circuits_ID\": 4, \"Circuit_name\": \"Circuit de Barcelona-Catalunya\"}, {\"Circuits_ID\": 12, \"Circuit_name\": \"Valencia Street Circuit\"}, {\"Circuits_ID\": 26, \"Circuit_name\": \"Circuito de Jerez\"}, {\"Circuits_ID\": 45, \"Circuit_name\": \"Jarama\"}, {\"Circuits_ID\": 49, \"Circuit_name\": \"Montjuïc\"}, {\"Circuits_ID\": 67, \"Circuit_name\": \"Circuit de Pedralbes\"}]}"},{"Country":"{\"Country\": \"Sri Lanka\", \"circuits\": null}"},{"Country":"{\"Country\": \"State of Palestine\", \"circuits\": null}"},{"Country":"{\"Country\": \"Sudan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Suriname\", \"circuits\": null}"},{"Country":"{\"Country\": \"Svalbard and Jan Mayen\", \"circuits\": null}"},{"Country":"{\"Country\": \"Swaziland\", \"circuits\": null}"},{"Country":"{\"Country\": \"Sweden\", \"circuits\": [{\"Circuits_ID\": 47, \"Circuit_name\": \"Scandinavian Raceway\"}]}"},{"Country":"{\"Country\": \"Switzerland\", \"circuits\": [{\"Circuits_ID\": 66, \"Circuit_name\": \"Circuit Bremgarten\"}]}"},{"Country":"{\"Country\": \"Syrian Arab Republic\", \"circuits\": null}"},{"Country":"{\"Country\": \"Taiwan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Tajikistan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Tanzania\", \"circuits\": null}"},{"Country":"{\"Country\": \"Thailand\", \"circuits\": null}"},{"Country":"{\"Country\": \"Timor-Leste\", \"circuits\": null}"},{"Country":"{\"Country\": \"Togo\", \"circuits\": null}"},{"Country":"{\"Country\": \"Tokelau\", \"circuits\": null}"},{"Country":"{\"Country\": \"Tonga\", \"circuits\": null}"},{"Country":"{\"Country\": \"Trinidad and Tobago\", \"circuits\": null}"},{"Country":"{\"Country\": \"Tristan da Cunha\", \"circuits\": null}"},{"Country":"{\"Country\": \"Tunisia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Turkey\", \"circuits\": [{\"Circuits_ID\": 5, \"Circuit_name\": \"Istanbul Park\"}]}"},{"Country":"{\"Country\": \"Turkmenistan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Turks and Caicos Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"Tuvalu\", \"circuits\": null}"},{"Country":"{\"Country\": \"Uganda\", \"circuits\": null}"},{"Country":"{\"Country\": \"Ukraine\", \"circuits\": null}"},{"Country":"{\"Country\": \"United Arab Emirates\", \"circuits\": [{\"Circuits_ID\": 24, \"Circuit_name\": \"Yas Marina Circuit\"}]}"},{"Country":"{\"Country\": \"United Kingdom\", \"circuits\": [{\"Circuits_ID\": 9, \"Circuit_name\": \"Silverstone Circuit\"}, {\"Circuits_ID\": 31, \"Circuit_name\": \"Donington Park\"}, {\"Circuits_ID\": 38, \"Circuit_name\": \"Brands Hatch\"}, {\"Circuits_ID\": 58, \"Circuit_name\": \"Aintree\"}]}"},{"Country":"{\"Country\": \"United Nations\", \"circuits\": null}"},{"Country":"{\"Country\": \"United States Minor Outlying Islands\", \"circuits\": null}"},{"Country":"{\"Country\": \"United States of America\", \"circuits\": [{\"Circuits_ID\": 19, \"Circuit_name\": \"Indianapolis Motor Speedway\"}, {\"Circuits_ID\": 33, \"Circuit_name\": \"Phoenix street circuit\"}, {\"Circuits_ID\": 37, \"Circuit_name\": \"Detroit Street Circuit\"}, {\"Circuits_ID\": 42, \"Circuit_name\": \"Fair Park\"}, {\"Circuits_ID\": 43, \"Circuit_name\": \"Long Beach\"}, {\"Circuits_ID\": 44, \"Circuit_name\": \"Las Vegas Street Circuit\"}, {\"Circuits_ID\": 46, \"Circuit_name\": \"Watkins Glen\"}, {\"Circuits_ID\": 60, \"Circuit_name\": \"Riverside International Raceway\"}, {\"Circuits_ID\": 63, \"Circuit_name\": \"Sebring International Raceway\"}, {\"Circuits_ID\": 69, \"Circuit_name\": \"Circuit of the Americas\"}, {\"Circuits_ID\": 72, \"Circuit_name\": \"Port Imperial Street Circuit\"}]}"},{"Country":"{\"Country\": \"Uruguay\", \"circuits\": null}"},{"Country":"{\"Country\": \"Uzbekistan\", \"circuits\": null}"},{"Country":"{\"Country\": \"Vanuatu\", \"circuits\": null}"},{"Country":"{\"Country\": \"Venezuela\", \"circuits\": null}"},{"Country":"{\"Country\": \"Vietnam\", \"circuits\": [{\"Circuits_ID\": 74, \"Circuit_name\": \"Hanoi Street Circuit\"}]}"},{"Country":"{\"Country\": \"Virgin Islands (British)\", \"circuits\": null}"},{"Country":"{\"Country\": \"Virgin Islands (U.S.)\", \"circuits\": null}"},{"Country":"{\"Country\": \"Wales\", \"circuits\": null}"},{"Country":"{\"Country\": \"Wallis and Futuna\", \"circuits\": null}"},{"Country":"{\"Country\": \"Western Sahara\", \"circuits\": null}"},{"Country":"{\"Country\": \"Yemen\", \"circuits\": null}"},{"Country":"{\"Country\": \"Zambia\", \"circuits\": null}"},{"Country":"{\"Country\": \"Zimbabwe\", \"circuits\": null}"}]}`</script>

CodePudding user response:

JSON.parse will be handy here to interpret the data as objects. Once that is done you can iterate through the list of countries adding to the main <ul>. If the circuit list is not null, create a new <ul> and append circuit names to that list.

const data = [{
    "Country": "{\"Country\": \"Aruba\", \"circuits\": null}"
  },
  {
    "Country": "{\"Country\": \"Ascension Island\", \"circuits\": null}"
  },
  {
    "Country": "{\"Country\": \"Australia\", \"circuits\": [{\"Circuits_ID\": 1, \"Circuit_name\": \"Albert Park Grand Prix Circuit\"}, {\"Circuits_ID\": 29, \"Circuit_name\": \"Adelaide Street Circuit\"}]}"
  },
  {
    "Country": "{\"Country\": \"Austria\", \"circuits\": [{\"Circuits_ID\": 23, \"Circuit_name\": \"A1-Ring\"}, {\"Circuits_ID\": 57, \"Circuit_name\": \"Zeltweg\"}, {\"Circuits_ID\": 70, \"Circuit_name\": \"Red Bull Ring\"}]}"
  },
  {
    "Country": "{\"Country\": \"Azerbaijan\", \"circuits\": [{\"Circuits_ID\": 73, \"Circuit_name\": \"Baku City Circuit\"}]}"
  },
  {
    "Country": "{\"Country\": \"Bahamas\", \"circuits\": null}"
  },
];

const outerList = document.getElementById("outerList");

data.forEach(country => {
  // parse the JSON string into an object
  const countryData = JSON.parse(country.Country);
  const countryEntry = document.createElement("li");
  countryEntry.textContent = countryData.Country;
  outerList.appendChild(countryEntry);
  
  // create circuit list if it is non-null
  if (countryData.circuits != null) {
    const innerList = document.createElement("ul");
    outerList.appendChild(innerList);
    countryData.circuits.forEach(circuit => {
      const circuitEntry = document.createElement("li");
      circuitEntry.textContent = circuit.Circuit_name;
      innerList.appendChild(circuitEntry);
    });
  }
});
<ul id="outerList"></ul>

  • Related