function JSONReporter(runner, options = {}) {
    Base.call(this, runner, options);

    var self = this;
    var tests = [];
    var pending = [];
    var failures = [];
    var passes = [];
    var output;

    if (options.reporterOption && options.reporterOption.output) {
      if (utils.isBrowser()) {
        throw createUnsupportedError('file output not supported in browser');
      }
      output = options.reporterOption.output;
    }

    runner.on(EVENT_TEST_END, function (test) {
      tests.push(test);
    });

    runner.on(EVENT_TEST_PASS, function (test) {
      passes.push(test);
    });

    runner.on(EVENT_TEST_FAIL, function (test) {
      failures.push(test);
    });

    runner.on(EVENT_TEST_PENDING, function (test) {
      pending.push(test);
    });

    runner.once(EVENT_RUN_END, function () {
      var obj = {
        stats: self.stats,
        tests: tests.map(clean),
        pending: pending.map(clean),
        failures: failures.map(clean),
        passes: passes.map(clean)
      };

      runner.testResults = obj;

      var json = JSON.stringify(obj, null, 2);
      if (output) {
        try {
          fs.mkdirSync(path.dirname(output), {recursive: true});
          fs.writeFileSync(output, json);
        } catch (err) {
          console.error(
            `${Base.symbols.err} [mocha] writing output to "${output}" failed: ${err.message}\n`
          );
          process.stdout.write(json);
        }
      } else {
        process.stdout.write(json);
      }
    });
  }
Constructs a new `JSON` reporter instance.

@public
@class JSON
@memberof Mocha.reporters
@extends Mocha.reporters.Base
@param {Runner} runner - Instance triggers reporter actions.
@param {Object} [options] - runner options