Read JSON safely

Each input line should be a JSON object with a name. Report what you find without letting a bad line stop the program.

What to build

A function that reads one line of JSON and handles the two different ways it can fail.

Requirements

For each line, print:

  • the name, if the line is valid JSON for an object whose name is a string;
  • invalid JSON, if JSON.parse cannot read the line;
  • no name, for any other valid JSON (no name, a name that is not a string, or not an object at all).

Input

Several lines of text.

Output

One line per input line.

Constraints

There are from 1 to 50 lines.

Example

Input:

{"name": "Mitu"}
{name: "Rahim"}
{"age": 3}

Output:

Mitu
invalid JSON
no name

Why it works

try covers only the parsing, so catch knows exactly which failure it is handling. Valid JSON can still be null or a number, so the shape of the data must be checked separately.

Examples

Example 1 · Input
{"name": "Mitu"}
{name: "Rahim"}
{"age": 3}
Expected output
Mitu
invalid JSON
no name
Example 2 · Input
{"name": "A", "age": 21}
Expected output
A

Hints

Hint 1

JSON.parse throws a SyntaxError for text that is not JSON: wrap it in try ... catch.

Hint 2

Valid JSON can still be a number, an array or null: check that you got an object with a string name.

Hint 3

typeof data === "object" && data !== null && typeof data.name === "string".

Solution

Show one correct solution (try it yourself first)
function nameOf(text) {
  let data;
  try {
    data = JSON.parse(text);
  } catch (err) {
    return "invalid JSON";
  }
  if (typeof data === "object" && data !== null && typeof data.name === "string") {
    return data.name;
  }
  return "no name";
}

let line = prompt();
while (line !== null) {
  console.log(nameOf(line));
  line = prompt();
}

Lesson: Errors: throw, try and catch →