Search code examples
javascriptkey-value

How to skip undefined/missing values in key-value pairs


I'm trying to build a citation generator from json in an API with data about images, stored in key-value pairs. I can get the data to return to the screen, but it always includes undefined in the citation. Sample manifest returns undefined as the creator since that isn't listed in this particular record. How can I keep any undefined value from being returned? I've tried changing the forEach to map, filtering at allMetadata by string length, using if !== undefined at insertCitation, and versions of those in different spots in the code.

EDIT: updated to provide full code, including print to page

(function () {
'use strict';

const buildCitation = {
    buildMetadataObject: async function (collAlias, itemID) {
        let response = await fetch('/iiif/info/' + collAlias + '/' + itemID + '/manifest.json');
        let data = await response.json()
        let allMetadata = data.metadata
        let citationData = {};
        allMetadata.forEach(function (kvpair) {
            if (kvpair.value == undefined) {
                return false;
            } else if (kvpair.label === 'Title') {
                citationData.itemTitle = kvpair.value;
            } else if (kvpair.label === 'Creator') {
                citationData.itemCreator = kvpair.value;
            } else if (kvpair.label === 'Repository') {
                citationData.itemRepository = kvpair.value;
            } else if (kvpair.label === 'Collection Name') {
                citationData.itemCollection = kvpair.value;
            } else if (kvpair.label === 'Owning Institution') {
                citationData.itemOwning = kvpair.value;
            } else if (kvpair.label === 'Date') {
                citationData.itemDate = kvpair.value;
            } else if (kvpair.label === 'Storage Location') {
                citationData.itemStorage = kvpair.value;
            }
        return true;
        });
        return citationData;
    },
    insertCitation: function (data) {
        var testTitle = data.itemTitle;
        console.log(testTitle);
        const itemCite = `Citation: "${data.itemTitle}," ${data.itemDate}, ${data.itemCreator}, ${data.itemCollection}, ${data.itemOwning}, ${data.itemStorage}, ${data.itemRepository}.`;
        const citationContainer = document.createElement('div');
        citationContainer.id = 'citation';
        citationContainer.innerHTML = itemCite;

        // CHANGED to innerHTML instead of innerText because you may want to format it at some point as HTML code.

        if (testTitle) {
            document.querySelector('.ItemView-itemViewContainer').appendChild(citationContainer);
        }
    }
}

document.addEventListener('cdm-item-page:ready', async function (e) {
    const citationData = await buildCitation.buildMetadataObject(e.detail.collectionId, e.detail.itemId);
    console.log({ citationData });
    buildCitation.insertCitation(citationData);
});

document.addEventListener('cdm-item-page:update', async function (e) {
    document.getElementById('citation').remove();
    const citationData = await buildCitation.buildMetadataObject(e.detail.collectionId, e.detail.itemId);
    console.log({ citationData });
    buildCitation.insertCitation(citationData);
});

})();


Solution

  • I've simplified your program. The undefined is coming from the fact that there is no item with label Date

    const mappings = {
      Date: 'itemDate',
      Title: 'itemTitle',
      Creator: 'itemCreator',
      Repository: 'itemRepository',
      'Storage Location': 'itemStorage',
      'Owning Institution': 'itemOwning',
      'Collection Name': 'itemCollection',
    }
    async function buildMetadataObject(collAlias, itemID) {
      let response = await fetch('https://teva.contentdm.oclc.org/iiif/info/p15138coll25/1421/manifest.json');
      let data = await response.json()
      return data.metadata.reduce(
        (acc, { label, value }) => ({ ...acc, [ mappings[label] ]: value }),
        {}
      )
    }
    
    function insertCitation(data) {
      var testTitle = data.itemTitle;
      const fieldBlackList = ['itemTitle'];
      const itemCite = `Citation: "${data.itemTitle}," ${
        Object.values(mappings).reduce((acc, cur) => {
          if (fieldBlackList.includes(cur)) return acc;
          const value = data[cur]; 
          return value ? [...acc, value] : acc 
        }, []).join(', ')
      }.`;
      console.log(itemCite);
    }
    //MAIN PROGRAM
    (async() => {
      const citationData = await buildMetadataObject();
      insertCitation(citationData);
    })()