static bool ParseCamera(Camera *camera, std::string *err, const json &o,
                        bool store_original_json_for_extras_and_extensions) {
  if (!ParseStringProperty(&camera->type, err, o, "type", true, "Camera")) {
    return false;
  }

  if (camera->type.compare("orthographic") == 0) {
    json_const_iterator orthoIt;
    if (!FindMember(o, "orthographic", orthoIt)) {
      if (err) {
        std::stringstream ss;
        ss << "Orhographic camera description not found." << std::endl;
        (*err) += ss.str();
      }
      return false;
    }

    const json &v = GetValue(orthoIt);
    if (!IsObject(v)) {
      if (err) {
        std::stringstream ss;
        ss << "\"orthographic\" is not a JSON object." << std::endl;
        (*err) += ss.str();
      }
      return false;
    }

    if (!ParseOrthographicCamera(
            &camera->orthographic, err, v,
            store_original_json_for_extras_and_extensions)) {
      return false;
    }
  } else if (camera->type.compare("perspective") == 0) {
    json_const_iterator perspIt;
    if (!FindMember(o, "perspective", perspIt)) {
      if (err) {
        std::stringstream ss;
        ss << "Perspective camera description not found." << std::endl;
        (*err) += ss.str();
      }
      return false;
    }

    const json &v = GetValue(perspIt);
    if (!IsObject(v)) {
      if (err) {
        std::stringstream ss;
        ss << "\"perspective\" is not a JSON object." << std::endl;
        (*err) += ss.str();
      }
      return false;
    }

    if (!ParsePerspectiveCamera(
            &camera->perspective, err, v,
            store_original_json_for_extras_and_extensions)) {
      return false;
    }
  } else {
    if (err) {
      std::stringstream ss;
      ss << "Invalid camera type: \"" << camera->type
         << "\". Must be \"perspective\" or \"orthographic\"" << std::endl;
      (*err) += ss.str();
    }
    return false;
  }

  ParseStringProperty(&camera->name, err, o, "name", false);

  ParseExtensionsProperty(&camera->extensions, err, o);
  ParseExtrasProperty(&(camera->extras), o);

  if (store_original_json_for_extras_and_extensions) {
    {
      json_const_iterator it;
      if (FindMember(o, "extensions", it)) {
        camera->extensions_json_string = JsonToString(GetValue(it));
      }
    }
    {
      json_const_iterator it;
      if (FindMember(o, "extras", it)) {
        camera->extras_json_string = JsonToString(GetValue(it));
      }
    }
  }

  return true;
}
static bool ParseCamera(Camera *camera, std::string *err, const json &o,
                        bool store_original_json_for_extras_and_extensions) {
  if (!ParseStringProperty(&camera->type, err, o, "type", true, "Camera")) {
    return false;
  }

  if (camera->type.compare("orthographic") == 0) {
    json_const_iterator orthoIt;
    if (!FindMember(o, "orthographic", orthoIt)) {
      if (err) {
        std::stringstream ss;
        ss << "Orhographic camera description not found." << std::endl;
        (*err) += ss.str();
      }
      return false;
    }

    const json &v = GetValue(orthoIt);
    if (!IsObject(v)) {
      if (err) {
        std::stringstream ss;
        ss << "\"orthographic\" is not a JSON object." << std::endl;
        (*err) += ss.str();
      }
      return false;
    }

    if (!ParseOrthographicCamera(
            &camera->orthographic, err, v,
            store_original_json_for_extras_and_extensions)) {
      return false;
    }
  } else if (camera->type.compare("perspective") == 0) {
    json_const_iterator perspIt;
    if (!FindMember(o, "perspective", perspIt)) {
      if (err) {
        std::stringstream ss;
        ss << "Perspective camera description not found." << std::endl;
        (*err) += ss.str();
      }
      return false;
    }

    const json &v = GetValue(perspIt);
    if (!IsObject(v)) {
      if (err) {
        std::stringstream ss;
        ss << "\"perspective\" is not a JSON object." << std::endl;
        (*err) += ss.str();
      }
      return false;
    }

    if (!ParsePerspectiveCamera(
            &camera->perspective, err, v,
            store_original_json_for_extras_and_extensions)) {
      return false;
    }
  } else {
    if (err) {
      std::stringstream ss;
      ss << "Invalid camera type: \"" << camera->type
         << "\". Must be \"perspective\" or \"orthographic\"" << std::endl;
      (*err) += ss.str();
    }
    return false;
  }

  ParseStringProperty(&camera->name, err, o, "name", false);

  ParseExtensionsProperty(&camera->extensions, err, o);
  ParseExtrasProperty(&(camera->extras), o);

  if (store_original_json_for_extras_and_extensions) {
    {
      json_const_iterator it;
      if (FindMember(o, "extensions", it)) {
        camera->extensions_json_string = JsonToString(GetValue(it));
      }
    }
    {
      json_const_iterator it;
      if (FindMember(o, "extras", it)) {
        camera->extras_json_string = JsonToString(GetValue(it));
      }
    }
  }

  return true;
}