0
\$\begingroup\$

I have to parse a json object that can be a string, array, array of strings and array of object. I realised that it's not good from the beginning that one object can be many types, but I can't change the code from upstream so I'll have to deal it in my code instead. I'm building a pixel library for modern browser so I'm not using jQuery or lodash. I'm supporting most modern browser and IE >= 9

Here's the example of the data that can be returned

"author": { "@type": "Person", "name": "Author" } 

Or

"author":[{"@type":"Person","name":"Author"}] 

Or

"author": 'Author' 

Or

"author": ['Author', 'Author1'] 

And this is my code.

 let obj = {}; try { const json = document.querySelector('div.json'); if (json) { let disc = JSON.parse(json.innerHTML); let authors = disc.author; if (typeof authors !== 'undefined' && Array.isArray(authors) && authors.length > 0) { authors = authors.map((author) => { if (typeof author === 'object' && author.name) { return author.name; } else { return author; } }); } if (typeof authors !== 'undefined' && !Array.isArray(authors) && typeof authors === 'object') { authors = [authors.name]; } if (typeof authors !== 'undefined' && typeof authors === 'string') { authors = authors.split(','); } obj.cAu: authors.join(','); } } catch (e) { } return obj; 

My question is, is there a better way to do this in a more efficient way?

\$\endgroup\$
1
  • \$\begingroup\$Could you include the content "div.json" has in your html. We need to have your sample json to be able to review your code.\$\endgroup\$
    – Tolani
    CommentedJul 22, 2016 at 23:27

1 Answer 1

2
\$\begingroup\$

Personally I would have written the function as below. One thing that stood out that I noticed is that you are not returning anything in the catch statement of your try. So there is a certain 'ambiguity' as to what the function will return.

Here is my reasoning for the code style below:

  1. I expect the invoker to provide me with the JSON string that needs to data extracted from it, so that I can perform some immediate input validation. If the input is falsey I will return an empty string.

  2. I check whether the parsed result is an instance of an array (undefined or null will not pass this check)

  3. If it is an instance of an array I will check whether it is an array of objects, otherwise I will assume it is a string. I map these entries, and join them with a comma and return the result

  4. if the type is of an object (and not array since we already checked for that), I will return the name property of that object.

Feel free to wrap this in a try'catch but make sure you return something on the catch. I assume the invoker is expecting a string back.

function parseAuthor(authorString){ if(!authorString){ return ''; } const authorObj = JSON.parse(authorString); if (typeof authorObj === 'string') { return authorObj; } if (authorObj instanceof Array) { entries = authorObj.map((a) => { if(typeof a === 'object' && a.name){ return a.name; } else { return a; } }); return entries.join(','); } if (typeof authorObj === 'object' && authorObj.name) { return authorObj.name; } return ''; } 
\$\endgroup\$

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.