static bool ParseAnimationChannel(
    AnimationChannel *channel, std::string *err, const json &o,
    bool store_original_json_for_extras_and_extensions) {
  int samplerIndex = -1;
  int targetIndex = -1;
  if (!ParseIntegerProperty(&samplerIndex, err, o, "sampler", true,
                            "AnimationChannel")) {
    if (err) {
      (*err) += "`sampler` field is missing in animation channels\n";
    }
    return false;
  }

  json_const_iterator targetIt;
  if (FindMember(o, "target", targetIt) && IsObject(GetValue(targetIt))) {
    const json &target_object = GetValue(targetIt);

    if (!ParseIntegerProperty(&targetIndex, err, target_object, "node", true)) {
      if (err) {
        (*err) += "`node` field is missing in animation.channels.target\n";
      }
      return false;
    }

    if (!ParseStringProperty(&channel->target_path, err, target_object, "path",
                             true)) {
      if (err) {
        (*err) += "`path` field is missing in animation.channels.target\n";
      }
      return false;
    }
    ParseExtensionsProperty(&channel->target_extensions, err, target_object);
    if (store_original_json_for_extras_and_extensions) {
      json_const_iterator it;
      if (FindMember(target_object, "extensions", it)) {
        channel->target_extensions_json_string = JsonToString(GetValue(it));
      }
    }
  }

  channel->sampler = samplerIndex;
  channel->target_node = targetIndex;

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

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

  return true;
}
static bool ParseAnimationChannel(
    AnimationChannel *channel, std::string *err, const json &o,
    bool store_original_json_for_extras_and_extensions) {
  int samplerIndex = -1;
  int targetIndex = -1;
  if (!ParseIntegerProperty(&samplerIndex, err, o, "sampler", true,
                            "AnimationChannel")) {
    if (err) {
      (*err) += "`sampler` field is missing in animation channels\n";
    }
    return false;
  }

  json_const_iterator targetIt;
  if (FindMember(o, "target", targetIt) && IsObject(GetValue(targetIt))) {
    const json &target_object = GetValue(targetIt);

    if (!ParseIntegerProperty(&targetIndex, err, target_object, "node", true)) {
      if (err) {
        (*err) += "`node` field is missing in animation.channels.target\n";
      }
      return false;
    }

    if (!ParseStringProperty(&channel->target_path, err, target_object, "path",
                             true)) {
      if (err) {
        (*err) += "`path` field is missing in animation.channels.target\n";
      }
      return false;
    }
    ParseExtensionsProperty(&channel->target_extensions, err, target_object);
    if (store_original_json_for_extras_and_extensions) {
      json_const_iterator it;
      if (FindMember(target_object, "extensions", it)) {
        channel->target_extensions_json_string = JsonToString(GetValue(it));
      }
    }
  }

  channel->sampler = samplerIndex;
  channel->target_node = targetIndex;

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

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

  return true;
}