// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// Code generated by Microsoft (R) TypeSpec Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

#include "key_vault_client.hpp"

#include "../private/package_version.hpp"

#include <azure/core/base64.hpp>
#include <azure/core/exception.hpp>
#include <azure/core/http/http.hpp>
#include <azure/core/http/http_status_code.hpp>
#include <azure/core/http/policies/policy.hpp>
#include <azure/core/internal/json/json.hpp>
#include <azure/core/io/body_stream.hpp>

// codegen: insert after includes
#include "azure/keyvault/shared/keyvault_challenge_based_auth.hpp"
#include "azure/keyvault/shared/keyvault_shared.hpp"

using Azure::Security::KeyVault::_internal::KeyVaultChallengeBasedAuthenticationPolicy;
using Azure::Security::KeyVault::_internal::UrlScope;
// codegen: end insert after includes
using namespace Azure::Security::KeyVault::Certificates::_detail;
// codegen: replace KeyVaultClient::KeyVaultClient
KeyVaultClient::KeyVaultClient(
    const std::string& url,
    const std::shared_ptr<const Core::Credentials::TokenCredential>& credential,
    const KeyVaultClientOptions& options)
    : m_url(url), m_apiVersion(options.ApiVersion)
{
  std::vector<std::unique_ptr<Core::Http::Policies::HttpPolicy>> perRetryPolicies;
  std::vector<std::unique_ptr<Core::Http::Policies::HttpPolicy>> perCallPolicies;

  {
    Core::Credentials::TokenRequestContext tokenRequestContext;
    tokenRequestContext.Scopes
        = {Azure::Security::KeyVault::_internal::UrlScope::GetScopeFromUrl(Azure::Core::Url(url))};
    perRetryPolicies.emplace_back(std::make_unique<KeyVaultChallengeBasedAuthenticationPolicy>(
        credential, tokenRequestContext));
  }

  m_pipeline = std::make_shared<Core::Http::_internal::HttpPipeline>(
      options,
      "security-keyvault-certificates",
      _detail::PackageVersion::ToString(),
      std::move(perRetryPolicies),
      std::move(perCallPolicies));
}
// codegen: end replace KeyVaultClient::KeyVaultClient

std::string KeyVaultClient::GetUrl() const { return m_url.GetAbsoluteUrl(); }

GetCertificatesPagedResponse KeyVaultClient::GetCertificates(
    const KeyVaultClientGetCertificatesOptions& options,
    const Core::Context& context) const
{
  Core::Url url;
  if (options.NextPageToken.empty())
  {
    url = m_url;
    url.AppendPath("certificates");

    url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));
    if (options.Maxresults.HasValue())
    {
      url.AppendQueryParameter("maxresults", std::to_string(options.Maxresults.Value()));
    }

    if (options.IncludePending.HasValue())
    {
      url.AppendQueryParameter("includePending", options.IncludePending.Value() ? "true" : "false");
    }
  }
  else
  {
    if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0)
    {
      url = Core::Url(options.NextPageToken);
      if (url.GetPort() == 0 && m_url.GetPort() != 0 && url.GetHost() == m_url.GetHost())
      {
        url.SetPort(m_url.GetPort());
      }
    }
    else
    {
      url = Core::Url(
          m_url.GetScheme() + "://" + m_url.GetHost() + ':' + std::to_string(m_url.GetPort()) + '/'
          + (options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1)
                                             : options.NextPageToken));
    }

    const auto qps = url.GetQueryParameters();
    if (qps.find("api-version") != qps.cend())
    {
      url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));
    }
  }

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  GetCertificatesPagedResponse response{};
  response.m_client = std::make_shared<KeyVaultClient>(*this);
  response.m_options = options;
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());
        if (jsonRoot.contains("nextLink") && !jsonRoot["nextLink"].is_null())
        {
          response.NextPageToken = jsonRoot["nextLink"].get<std::string>();
        }

        if (jsonRoot.contains("value") && !jsonRoot["value"].is_null())
        {
          response.Value = std::vector<Models::CertificateItem>{};

          for (auto const& jsonItem : jsonRoot["value"])
          {
            Models::CertificateItem vectorItem{};

            if (jsonItem.contains("id") && !jsonItem["id"].is_null())
            {
              vectorItem.Id = jsonItem["id"].get<std::string>();
            }

            if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null())
            {
              vectorItem.Attributes = Models::CertificateAttributes{};

              if (jsonItem["attributes"].contains("enabled")
                  && !jsonItem["attributes"]["enabled"].is_null())
              {
                vectorItem.Attributes.Value().Enabled
                    = jsonItem["attributes"]["enabled"].get<bool>();
              }

              if (jsonItem["attributes"].contains("nbf")
                  && !jsonItem["attributes"]["nbf"].is_null())
              {
                vectorItem.Attributes.Value().NotBefore
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["nbf"].is_string()
                            ? std::stoll(jsonItem["attributes"]["nbf"].get<std::string>())
                            : jsonItem["attributes"]["nbf"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("exp")
                  && !jsonItem["attributes"]["exp"].is_null())
              {
                vectorItem.Attributes.Value().Expires
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["exp"].is_string()
                            ? std::stoll(jsonItem["attributes"]["exp"].get<std::string>())
                            : jsonItem["attributes"]["exp"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("created")
                  && !jsonItem["attributes"]["created"].is_null())
              {
                vectorItem.Attributes.Value().Created
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["created"].is_string()
                            ? std::stoll(jsonItem["attributes"]["created"].get<std::string>())
                            : jsonItem["attributes"]["created"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("updated")
                  && !jsonItem["attributes"]["updated"].is_null())
              {
                vectorItem.Attributes.Value().Updated
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["updated"].is_string()
                            ? std::stoll(jsonItem["attributes"]["updated"].get<std::string>())
                            : jsonItem["attributes"]["updated"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("recoverableDays")
                  && !jsonItem["attributes"]["recoverableDays"].is_null())
              {
                vectorItem.Attributes.Value().RecoverableDays
                    = jsonItem["attributes"]["recoverableDays"].is_string()
                    ? std::stoi(jsonItem["attributes"]["recoverableDays"].get<std::string>())
                    : jsonItem["attributes"]["recoverableDays"].get<std::int32_t>();
              }

              if (jsonItem["attributes"].contains("recoveryLevel")
                  && !jsonItem["attributes"]["recoveryLevel"].is_null())
              {
                vectorItem.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                    jsonItem["attributes"]["recoveryLevel"].get<std::string>());
              }
            }

            if (jsonItem.contains("tags") && !jsonItem["tags"].is_null())
            {
              vectorItem.Tags = std::map<std::string, std::string>{};

              for (auto const& kv : jsonItem["tags"].items())
              {
                std::string value{};
                value = kv.value().get<std::string>();
                vectorItem.Tags.Value().emplace(kv.key(), value);
              }
            }

            if (jsonItem.contains("x5t") && !jsonItem["x5t"].is_null())
            {
              vectorItem.X509Thumbprint
                  = Core::_internal::Base64Url::Base64UrlDecode(jsonItem["x5t"].get<std::string>());
            }

            response.Value.Value().emplace_back(std::move(vectorItem));
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  response.RawResponse = std::move(rawResponse);

  return response;
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::DeletedCertificateBundle>
KeyVaultClient::DeleteCertificate(const std::string& certificateName, const Core::Context& context)
    const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Delete, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::DeletedCertificateBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

        if (jsonRoot.contains("sid") && !jsonRoot["sid"].is_null())
        {
          response.Sid = jsonRoot["sid"].get<std::string>();
        }

        if (jsonRoot.contains("x5t") && !jsonRoot["x5t"].is_null())
        {
          response.X509Thumbprint
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["x5t"].get<std::string>());
        }

        if (jsonRoot.contains("policy") && !jsonRoot["policy"].is_null())
        {
          response.Policy = Models::CertificatePolicy{};

          if (jsonRoot["policy"].contains("id") && !jsonRoot["policy"]["id"].is_null())
          {
            response.Policy.Value().Id = jsonRoot["policy"]["id"].get<std::string>();
          }

          if (jsonRoot["policy"].contains("key_props")
              && !jsonRoot["policy"]["key_props"].is_null())
          {
            response.Policy.Value().KeyProperties = Models::KeyProperties{};

            if (jsonRoot["policy"]["key_props"].contains("exportable")
                && !jsonRoot["policy"]["key_props"]["exportable"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Exportable
                  = jsonRoot["policy"]["key_props"]["exportable"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("kty")
                && !jsonRoot["policy"]["key_props"]["kty"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeyType = Models::JsonWebKeyType(
                  jsonRoot["policy"]["key_props"]["kty"].get<std::string>());
            }

            if (jsonRoot["policy"]["key_props"].contains("key_size")
                && !jsonRoot["policy"]["key_props"]["key_size"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeySize
                  = jsonRoot["policy"]["key_props"]["key_size"].is_string()
                  ? std::stoi(jsonRoot["policy"]["key_props"]["key_size"].get<std::string>())
                  : jsonRoot["policy"]["key_props"]["key_size"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["key_props"].contains("reuse_key")
                && !jsonRoot["policy"]["key_props"]["reuse_key"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().ReuseKey
                  = jsonRoot["policy"]["key_props"]["reuse_key"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("crv")
                && !jsonRoot["policy"]["key_props"]["crv"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Curve = Models::JsonWebKeyCurveName(
                  jsonRoot["policy"]["key_props"]["crv"].get<std::string>());
            }
          }

          if (jsonRoot["policy"].contains("secret_props")
              && !jsonRoot["policy"]["secret_props"].is_null())
          {
            response.Policy.Value().SecretProperties = Models::SecretProperties{};

            if (jsonRoot["policy"]["secret_props"].contains("contentType")
                && !jsonRoot["policy"]["secret_props"]["contentType"].is_null())
            {
              response.Policy.Value().SecretProperties.Value().ContentType
                  = jsonRoot["policy"]["secret_props"]["contentType"].get<std::string>();
            }
          }

          if (jsonRoot["policy"].contains("x509_props")
              && !jsonRoot["policy"]["x509_props"].is_null())
          {
            response.Policy.Value().X509CertificateProperties = Models::X509CertificateProperties{};

            if (jsonRoot["policy"]["x509_props"].contains("subject")
                && !jsonRoot["policy"]["x509_props"]["subject"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Subject
                  = jsonRoot["policy"]["x509_props"]["subject"].get<std::string>();
            }

            if (jsonRoot["policy"]["x509_props"].contains("ekus")
                && !jsonRoot["policy"]["x509_props"]["ekus"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Ekus
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["ekus"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.Policy.Value().X509CertificateProperties.Value().Ekus.Value().emplace_back(
                    std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("sans")
                && !jsonRoot["policy"]["x509_props"]["sans"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().SubjectAlternativeNames
                  = Models::SubjectAlternativeNames{};

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("emails")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["emails"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["emails"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("dns_names")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["dns_names"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["dns_names"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("upns")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["upns"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["upns"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("key_usage")
                && !jsonRoot["policy"]["x509_props"]["key_usage"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().KeyUsage
                  = std::vector<Models::KeyUsageType>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["key_usage"])
              {
                Models::KeyUsageType vectorItem{};

                vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .KeyUsage.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("validity_months")
                && !jsonRoot["policy"]["x509_props"]["validity_months"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().ValidityInMonths
                  = jsonRoot["policy"]["x509_props"]["validity_months"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["x509_props"]["validity_months"].get<std::string>())
                  : jsonRoot["policy"]["x509_props"]["validity_months"].get<std::int32_t>();
            }
          }

          if (jsonRoot["policy"].contains("lifetime_actions")
              && !jsonRoot["policy"]["lifetime_actions"].is_null())
          {
            response.Policy.Value().LifetimeActions = std::vector<Models::LifetimeAction>{};

            for (auto const& jsonItem : jsonRoot["policy"]["lifetime_actions"])
            {
              Models::LifetimeAction vectorItem{};

              if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
              {
                vectorItem.Trigger = Models::Trigger{};

                if (jsonItem["trigger"].contains("lifetime_percentage")
                    && !jsonItem["trigger"]["lifetime_percentage"].is_null())
                {
                  vectorItem.Trigger.Value().LifetimePercentage
                      = jsonItem["trigger"]["lifetime_percentage"].is_string()
                      ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                      : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
                }

                if (jsonItem["trigger"].contains("days_before_expiry")
                    && !jsonItem["trigger"]["days_before_expiry"].is_null())
                {
                  vectorItem.Trigger.Value().DaysBeforeExpiry
                      = jsonItem["trigger"]["days_before_expiry"].is_string()
                      ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                      : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
                }
              }

              if (jsonItem.contains("action") && !jsonItem["action"].is_null())
              {
                vectorItem.Action = Models::Action{};

                if (jsonItem["action"].contains("action_type")
                    && !jsonItem["action"]["action_type"].is_null())
                {
                  vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                      jsonItem["action"]["action_type"].get<std::string>());
                }
              }

              response.Policy.Value().LifetimeActions.Value().emplace_back(std::move(vectorItem));
            }
          }

          if (jsonRoot["policy"].contains("issuer") && !jsonRoot["policy"]["issuer"].is_null())
          {
            response.Policy.Value().IssuerParameters = Models::IssuerParameters{};

            if (jsonRoot["policy"]["issuer"].contains("name")
                && !jsonRoot["policy"]["issuer"]["name"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().Name
                  = jsonRoot["policy"]["issuer"]["name"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cty")
                && !jsonRoot["policy"]["issuer"]["cty"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateType
                  = jsonRoot["policy"]["issuer"]["cty"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cert_transparency")
                && !jsonRoot["policy"]["issuer"]["cert_transparency"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateTransparency
                  = jsonRoot["policy"]["issuer"]["cert_transparency"].get<bool>();
            }
          }

          if (jsonRoot["policy"].contains("attributes")
              && !jsonRoot["policy"]["attributes"].is_null())
          {
            response.Policy.Value().Attributes = Models::CertificateAttributes{};

            if (jsonRoot["policy"]["attributes"].contains("enabled")
                && !jsonRoot["policy"]["attributes"]["enabled"].is_null())
            {
              response.Policy.Value().Attributes.Value().Enabled
                  = jsonRoot["policy"]["attributes"]["enabled"].get<bool>();
            }

            if (jsonRoot["policy"]["attributes"].contains("nbf")
                && !jsonRoot["policy"]["attributes"]["nbf"].is_null())
            {
              response.Policy.Value().Attributes.Value().NotBefore
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["nbf"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["nbf"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["nbf"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("exp")
                && !jsonRoot["policy"]["attributes"]["exp"].is_null())
            {
              response.Policy.Value().Attributes.Value().Expires
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["exp"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["exp"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["exp"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("created")
                && !jsonRoot["policy"]["attributes"]["created"].is_null())
            {
              response.Policy.Value().Attributes.Value().Created
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["created"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["created"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["created"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("updated")
                && !jsonRoot["policy"]["attributes"]["updated"].is_null())
            {
              response.Policy.Value().Attributes.Value().Updated
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["updated"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["updated"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["updated"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("recoverableDays")
                && !jsonRoot["policy"]["attributes"]["recoverableDays"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoverableDays
                  = jsonRoot["policy"]["attributes"]["recoverableDays"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::string>())
                  : jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["attributes"].contains("recoveryLevel")
                && !jsonRoot["policy"]["attributes"]["recoveryLevel"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoveryLevel
                  = Models::DeletionRecoveryLevel(
                      jsonRoot["policy"]["attributes"]["recoveryLevel"].get<std::string>());
            }
          }
        }

        if (jsonRoot.contains("cer") && !jsonRoot["cer"].is_null())
        {
          response.Cer = Core::Convert::Base64Decode(jsonRoot["cer"].get<std::string>());
        }

        if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null())
        {
          response.ContentType = jsonRoot["contentType"].get<std::string>();
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }

        if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null())
        {
          response.Tags = std::map<std::string, std::string>{};

          for (auto const& kv : jsonRoot["tags"].items())
          {
            std::string value{};
            value = kv.value().get<std::string>();
            response.Tags.Value().emplace(kv.key(), value);
          }
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }

        if (jsonRoot.contains("recoveryId") && !jsonRoot["recoveryId"].is_null())
        {
          response.RecoveryId = jsonRoot["recoveryId"].get<std::string>();
        }

        if (jsonRoot.contains("scheduledPurgeDate") && !jsonRoot["scheduledPurgeDate"].is_null())
        {
          response.ScheduledPurgeDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
              jsonRoot["scheduledPurgeDate"].is_string()
                  ? std::stoll(jsonRoot["scheduledPurgeDate"].get<std::string>())
                  : jsonRoot["scheduledPurgeDate"].get<std::int64_t>());
        }

        if (jsonRoot.contains("deletedDate") && !jsonRoot["deletedDate"].is_null())
        {
          response.DeletedDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
              jsonRoot["deletedDate"].is_string()
                  ? std::stoll(jsonRoot["deletedDate"].get<std::string>())
                  : jsonRoot["deletedDate"].get<std::int64_t>());
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::DeletedCertificateBundle>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::Contacts> KeyVaultClient::
    SetCertificateContacts(const Models::Contacts& contacts, const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/contacts");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    if (contacts.Id.HasValue())
    {
      jsonRoot["id"] = contacts.Id.Value();
    }

    if (contacts.ContactList.HasValue())
    {
      jsonRoot["contacts"] = Core::Json::_internal::json::array();

      const size_t size = contacts.ContactList.Value().size();
      for (size_t i = 0; i < size; ++i)
      {
        if (contacts.ContactList.Value()[i].EmailAddress.HasValue())
        {
          jsonRoot["contacts"][i]["email"] = contacts.ContactList.Value()[i].EmailAddress.Value();
        }

        if (contacts.ContactList.Value()[i].Name.HasValue())
        {
          jsonRoot["contacts"][i]["name"] = contacts.ContactList.Value()[i].Name.Value();
        }

        if (contacts.ContactList.Value()[i].Phone.HasValue())
        {
          jsonRoot["contacts"][i]["phone"] = contacts.ContactList.Value()[i].Phone.Value();
        }
      }
    }

    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Put, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::Contacts response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("contacts") && !jsonRoot["contacts"].is_null())
        {
          response.ContactList = std::vector<Models::Contact>{};

          for (auto const& jsonItem : jsonRoot["contacts"])
          {
            Models::Contact vectorItem{};

            if (jsonItem.contains("email") && !jsonItem["email"].is_null())
            {
              vectorItem.EmailAddress = jsonItem["email"].get<std::string>();
            }

            if (jsonItem.contains("name") && !jsonItem["name"].is_null())
            {
              vectorItem.Name = jsonItem["name"].get<std::string>();
            }

            if (jsonItem.contains("phone") && !jsonItem["phone"].is_null())
            {
              vectorItem.Phone = jsonItem["phone"].get<std::string>();
            }

            response.ContactList.Value().emplace_back(std::move(vectorItem));
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::Contacts>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::Contacts>
KeyVaultClient::GetCertificateContacts(const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/contacts");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::Contacts response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("contacts") && !jsonRoot["contacts"].is_null())
        {
          response.ContactList = std::vector<Models::Contact>{};

          for (auto const& jsonItem : jsonRoot["contacts"])
          {
            Models::Contact vectorItem{};

            if (jsonItem.contains("email") && !jsonItem["email"].is_null())
            {
              vectorItem.EmailAddress = jsonItem["email"].get<std::string>();
            }

            if (jsonItem.contains("name") && !jsonItem["name"].is_null())
            {
              vectorItem.Name = jsonItem["name"].get<std::string>();
            }

            if (jsonItem.contains("phone") && !jsonItem["phone"].is_null())
            {
              vectorItem.Phone = jsonItem["phone"].get<std::string>();
            }

            response.ContactList.Value().emplace_back(std::move(vectorItem));
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::Contacts>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::Contacts>
KeyVaultClient::DeleteCertificateContacts(const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/contacts");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Delete, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::Contacts response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("contacts") && !jsonRoot["contacts"].is_null())
        {
          response.ContactList = std::vector<Models::Contact>{};

          for (auto const& jsonItem : jsonRoot["contacts"])
          {
            Models::Contact vectorItem{};

            if (jsonItem.contains("email") && !jsonItem["email"].is_null())
            {
              vectorItem.EmailAddress = jsonItem["email"].get<std::string>();
            }

            if (jsonItem.contains("name") && !jsonItem["name"].is_null())
            {
              vectorItem.Name = jsonItem["name"].get<std::string>();
            }

            if (jsonItem.contains("phone") && !jsonItem["phone"].is_null())
            {
              vectorItem.Phone = jsonItem["phone"].get<std::string>();
            }

            response.ContactList.Value().emplace_back(std::move(vectorItem));
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::Contacts>(std::move(response), std::move(rawResponse));
}

GetCertificateIssuersPagedResponse KeyVaultClient::GetCertificateIssuers(
    const KeyVaultClientGetCertificateIssuersOptions& options,
    const Core::Context& context) const
{
  Core::Url url;
  if (options.NextPageToken.empty())
  {
    url = m_url;
    url.AppendPath("certificates/issuers");

    url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));
    if (options.Maxresults.HasValue())
    {
      url.AppendQueryParameter("maxresults", std::to_string(options.Maxresults.Value()));
    }
  }
  else
  {
    if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0)
    {
      url = Core::Url(options.NextPageToken);
      if (url.GetPort() == 0 && m_url.GetPort() != 0 && url.GetHost() == m_url.GetHost())
      {
        url.SetPort(m_url.GetPort());
      }
    }
    else
    {
      url = Core::Url(
          m_url.GetScheme() + "://" + m_url.GetHost() + ':' + std::to_string(m_url.GetPort()) + '/'
          + (options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1)
                                             : options.NextPageToken));
    }

    const auto qps = url.GetQueryParameters();
    if (qps.find("api-version") != qps.cend())
    {
      url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));
    }
  }

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  GetCertificateIssuersPagedResponse response{};
  response.m_client = std::make_shared<KeyVaultClient>(*this);
  response.m_options = options;
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());
        if (jsonRoot.contains("nextLink") && !jsonRoot["nextLink"].is_null())
        {
          response.NextPageToken = jsonRoot["nextLink"].get<std::string>();
        }

        if (jsonRoot.contains("value") && !jsonRoot["value"].is_null())
        {
          response.Value = std::vector<Models::CertificateIssuerItem>{};

          for (auto const& jsonItem : jsonRoot["value"])
          {
            Models::CertificateIssuerItem vectorItem{};

            if (jsonItem.contains("id") && !jsonItem["id"].is_null())
            {
              vectorItem.Id = jsonItem["id"].get<std::string>();
            }

            if (jsonItem.contains("provider") && !jsonItem["provider"].is_null())
            {
              vectorItem.Provider = jsonItem["provider"].get<std::string>();
            }

            response.Value.Value().emplace_back(std::move(vectorItem));
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  response.RawResponse = std::move(rawResponse);

  return response;
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::IssuerBundle>
KeyVaultClient::SetCertificateIssuer(
    const std::string& issuerName,
    const Models::CertificateIssuerSetParameters& parameter,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/issuers/");
  if (issuerName.empty())
  {
    throw std::invalid_argument("Parameter 'issuerName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(issuerName));

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["provider"] = parameter.Provider;
    if (parameter.Credentials.HasValue())
    {
      if (parameter.Credentials.Value().AccountId.HasValue())
      {
        jsonRoot["credentials"]["account_id"] = parameter.Credentials.Value().AccountId.Value();
      }

      if (parameter.Credentials.Value().Password.HasValue())
      {
        jsonRoot["credentials"]["pwd"] = parameter.Credentials.Value().Password.Value();
      }
    }

    if (parameter.OrganizationDetails.HasValue())
    {
      if (parameter.OrganizationDetails.Value().Id.HasValue())
      {
        jsonRoot["org_details"]["id"] = parameter.OrganizationDetails.Value().Id.Value();
      }

      if (parameter.OrganizationDetails.Value().AdminDetails.HasValue())
      {
        jsonRoot["org_details"]["admin_details"] = Core::Json::_internal::json::array();

        const size_t size = parameter.OrganizationDetails.Value().AdminDetails.Value().size();
        for (size_t i = 0; i < size; ++i)
        {
          if (parameter.OrganizationDetails.Value().AdminDetails.Value()[i].FirstName.HasValue())
          {
            jsonRoot["org_details"]["admin_details"][i]["first_name"]
                = parameter.OrganizationDetails.Value().AdminDetails.Value()[i].FirstName.Value();
          }

          if (parameter.OrganizationDetails.Value().AdminDetails.Value()[i].LastName.HasValue())
          {
            jsonRoot["org_details"]["admin_details"][i]["last_name"]
                = parameter.OrganizationDetails.Value().AdminDetails.Value()[i].LastName.Value();
          }

          if (parameter.OrganizationDetails.Value().AdminDetails.Value()[i].EmailAddress.HasValue())
          {
            jsonRoot["org_details"]["admin_details"][i]["email"]
                = parameter.OrganizationDetails.Value()
                      .AdminDetails.Value()[i]
                      .EmailAddress.Value();
          }

          if (parameter.OrganizationDetails.Value().AdminDetails.Value()[i].Phone.HasValue())
          {
            jsonRoot["org_details"]["admin_details"][i]["phone"]
                = parameter.OrganizationDetails.Value().AdminDetails.Value()[i].Phone.Value();
          }
        }
      }
    }

    if (parameter.Attributes.HasValue())
    {
      if (parameter.Attributes.Value().Enabled.HasValue())
      {
        jsonRoot["attributes"]["enabled"] = parameter.Attributes.Value().Enabled.Value();
      }

      if (parameter.Attributes.Value().Created.HasValue())
      {
        jsonRoot["attributes"]["created"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameter.Attributes.Value().Created.Value());
      }

      if (parameter.Attributes.Value().Updated.HasValue())
      {
        jsonRoot["attributes"]["updated"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameter.Attributes.Value().Updated.Value());
      }
    }

    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Put, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::IssuerBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("provider") && !jsonRoot["provider"].is_null())
        {
          response.Provider = jsonRoot["provider"].get<std::string>();
        }

        if (jsonRoot.contains("credentials") && !jsonRoot["credentials"].is_null())
        {
          response.Credentials = Models::IssuerCredentials{};

          if (jsonRoot["credentials"].contains("account_id")
              && !jsonRoot["credentials"]["account_id"].is_null())
          {
            response.Credentials.Value().AccountId
                = jsonRoot["credentials"]["account_id"].get<std::string>();
          }

          if (jsonRoot["credentials"].contains("pwd") && !jsonRoot["credentials"]["pwd"].is_null())
          {
            response.Credentials.Value().Password
                = jsonRoot["credentials"]["pwd"].get<std::string>();
          }
        }

        if (jsonRoot.contains("org_details") && !jsonRoot["org_details"].is_null())
        {
          response.OrganizationDetails = Models::OrganizationDetails{};

          if (jsonRoot["org_details"].contains("id") && !jsonRoot["org_details"]["id"].is_null())
          {
            response.OrganizationDetails.Value().Id
                = jsonRoot["org_details"]["id"].get<std::string>();
          }

          if (jsonRoot["org_details"].contains("admin_details")
              && !jsonRoot["org_details"]["admin_details"].is_null())
          {
            response.OrganizationDetails.Value().AdminDetails
                = std::vector<Models::AdministratorDetails>{};

            for (auto const& jsonItem : jsonRoot["org_details"]["admin_details"])
            {
              Models::AdministratorDetails vectorItem{};

              if (jsonItem.contains("first_name") && !jsonItem["first_name"].is_null())
              {
                vectorItem.FirstName = jsonItem["first_name"].get<std::string>();
              }

              if (jsonItem.contains("last_name") && !jsonItem["last_name"].is_null())
              {
                vectorItem.LastName = jsonItem["last_name"].get<std::string>();
              }

              if (jsonItem.contains("email") && !jsonItem["email"].is_null())
              {
                vectorItem.EmailAddress = jsonItem["email"].get<std::string>();
              }

              if (jsonItem.contains("phone") && !jsonItem["phone"].is_null())
              {
                vectorItem.Phone = jsonItem["phone"].get<std::string>();
              }

              response.OrganizationDetails.Value().AdminDetails.Value().emplace_back(
                  std::move(vectorItem));
            }
          }
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::IssuerAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::IssuerBundle>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::IssuerBundle>
KeyVaultClient::UpdateCertificateIssuer(
    const std::string& issuerName,
    const Models::CertificateIssuerUpdateParameters& parameter,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/issuers/");
  if (issuerName.empty())
  {
    throw std::invalid_argument("Parameter 'issuerName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(issuerName));

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    if (parameter.Provider.HasValue())
    {
      jsonRoot["provider"] = parameter.Provider.Value();
    }

    if (parameter.Credentials.HasValue())
    {
      if (parameter.Credentials.Value().AccountId.HasValue())
      {
        jsonRoot["credentials"]["account_id"] = parameter.Credentials.Value().AccountId.Value();
      }

      if (parameter.Credentials.Value().Password.HasValue())
      {
        jsonRoot["credentials"]["pwd"] = parameter.Credentials.Value().Password.Value();
      }
    }

    if (parameter.OrganizationDetails.HasValue())
    {
      if (parameter.OrganizationDetails.Value().Id.HasValue())
      {
        jsonRoot["org_details"]["id"] = parameter.OrganizationDetails.Value().Id.Value();
      }

      if (parameter.OrganizationDetails.Value().AdminDetails.HasValue())
      {
        jsonRoot["org_details"]["admin_details"] = Core::Json::_internal::json::array();

        const size_t size = parameter.OrganizationDetails.Value().AdminDetails.Value().size();
        for (size_t i = 0; i < size; ++i)
        {
          if (parameter.OrganizationDetails.Value().AdminDetails.Value()[i].FirstName.HasValue())
          {
            jsonRoot["org_details"]["admin_details"][i]["first_name"]
                = parameter.OrganizationDetails.Value().AdminDetails.Value()[i].FirstName.Value();
          }

          if (parameter.OrganizationDetails.Value().AdminDetails.Value()[i].LastName.HasValue())
          {
            jsonRoot["org_details"]["admin_details"][i]["last_name"]
                = parameter.OrganizationDetails.Value().AdminDetails.Value()[i].LastName.Value();
          }

          if (parameter.OrganizationDetails.Value().AdminDetails.Value()[i].EmailAddress.HasValue())
          {
            jsonRoot["org_details"]["admin_details"][i]["email"]
                = parameter.OrganizationDetails.Value()
                      .AdminDetails.Value()[i]
                      .EmailAddress.Value();
          }

          if (parameter.OrganizationDetails.Value().AdminDetails.Value()[i].Phone.HasValue())
          {
            jsonRoot["org_details"]["admin_details"][i]["phone"]
                = parameter.OrganizationDetails.Value().AdminDetails.Value()[i].Phone.Value();
          }
        }
      }
    }

    if (parameter.Attributes.HasValue())
    {
      if (parameter.Attributes.Value().Enabled.HasValue())
      {
        jsonRoot["attributes"]["enabled"] = parameter.Attributes.Value().Enabled.Value();
      }

      if (parameter.Attributes.Value().Created.HasValue())
      {
        jsonRoot["attributes"]["created"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameter.Attributes.Value().Created.Value());
      }

      if (parameter.Attributes.Value().Updated.HasValue())
      {
        jsonRoot["attributes"]["updated"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameter.Attributes.Value().Updated.Value());
      }
    }

    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Patch, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::IssuerBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("provider") && !jsonRoot["provider"].is_null())
        {
          response.Provider = jsonRoot["provider"].get<std::string>();
        }

        if (jsonRoot.contains("credentials") && !jsonRoot["credentials"].is_null())
        {
          response.Credentials = Models::IssuerCredentials{};

          if (jsonRoot["credentials"].contains("account_id")
              && !jsonRoot["credentials"]["account_id"].is_null())
          {
            response.Credentials.Value().AccountId
                = jsonRoot["credentials"]["account_id"].get<std::string>();
          }

          if (jsonRoot["credentials"].contains("pwd") && !jsonRoot["credentials"]["pwd"].is_null())
          {
            response.Credentials.Value().Password
                = jsonRoot["credentials"]["pwd"].get<std::string>();
          }
        }

        if (jsonRoot.contains("org_details") && !jsonRoot["org_details"].is_null())
        {
          response.OrganizationDetails = Models::OrganizationDetails{};

          if (jsonRoot["org_details"].contains("id") && !jsonRoot["org_details"]["id"].is_null())
          {
            response.OrganizationDetails.Value().Id
                = jsonRoot["org_details"]["id"].get<std::string>();
          }

          if (jsonRoot["org_details"].contains("admin_details")
              && !jsonRoot["org_details"]["admin_details"].is_null())
          {
            response.OrganizationDetails.Value().AdminDetails
                = std::vector<Models::AdministratorDetails>{};

            for (auto const& jsonItem : jsonRoot["org_details"]["admin_details"])
            {
              Models::AdministratorDetails vectorItem{};

              if (jsonItem.contains("first_name") && !jsonItem["first_name"].is_null())
              {
                vectorItem.FirstName = jsonItem["first_name"].get<std::string>();
              }

              if (jsonItem.contains("last_name") && !jsonItem["last_name"].is_null())
              {
                vectorItem.LastName = jsonItem["last_name"].get<std::string>();
              }

              if (jsonItem.contains("email") && !jsonItem["email"].is_null())
              {
                vectorItem.EmailAddress = jsonItem["email"].get<std::string>();
              }

              if (jsonItem.contains("phone") && !jsonItem["phone"].is_null())
              {
                vectorItem.Phone = jsonItem["phone"].get<std::string>();
              }

              response.OrganizationDetails.Value().AdminDetails.Value().emplace_back(
                  std::move(vectorItem));
            }
          }
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::IssuerAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::IssuerBundle>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::IssuerBundle>
KeyVaultClient::GetCertificateIssuer(const std::string& issuerName, const Core::Context& context)
    const
{
  auto url = m_url;
  url.AppendPath("certificates/issuers/");
  if (issuerName.empty())
  {
    throw std::invalid_argument("Parameter 'issuerName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(issuerName));

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::IssuerBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("provider") && !jsonRoot["provider"].is_null())
        {
          response.Provider = jsonRoot["provider"].get<std::string>();
        }

        if (jsonRoot.contains("credentials") && !jsonRoot["credentials"].is_null())
        {
          response.Credentials = Models::IssuerCredentials{};

          if (jsonRoot["credentials"].contains("account_id")
              && !jsonRoot["credentials"]["account_id"].is_null())
          {
            response.Credentials.Value().AccountId
                = jsonRoot["credentials"]["account_id"].get<std::string>();
          }

          if (jsonRoot["credentials"].contains("pwd") && !jsonRoot["credentials"]["pwd"].is_null())
          {
            response.Credentials.Value().Password
                = jsonRoot["credentials"]["pwd"].get<std::string>();
          }
        }

        if (jsonRoot.contains("org_details") && !jsonRoot["org_details"].is_null())
        {
          response.OrganizationDetails = Models::OrganizationDetails{};

          if (jsonRoot["org_details"].contains("id") && !jsonRoot["org_details"]["id"].is_null())
          {
            response.OrganizationDetails.Value().Id
                = jsonRoot["org_details"]["id"].get<std::string>();
          }

          if (jsonRoot["org_details"].contains("admin_details")
              && !jsonRoot["org_details"]["admin_details"].is_null())
          {
            response.OrganizationDetails.Value().AdminDetails
                = std::vector<Models::AdministratorDetails>{};

            for (auto const& jsonItem : jsonRoot["org_details"]["admin_details"])
            {
              Models::AdministratorDetails vectorItem{};

              if (jsonItem.contains("first_name") && !jsonItem["first_name"].is_null())
              {
                vectorItem.FirstName = jsonItem["first_name"].get<std::string>();
              }

              if (jsonItem.contains("last_name") && !jsonItem["last_name"].is_null())
              {
                vectorItem.LastName = jsonItem["last_name"].get<std::string>();
              }

              if (jsonItem.contains("email") && !jsonItem["email"].is_null())
              {
                vectorItem.EmailAddress = jsonItem["email"].get<std::string>();
              }

              if (jsonItem.contains("phone") && !jsonItem["phone"].is_null())
              {
                vectorItem.Phone = jsonItem["phone"].get<std::string>();
              }

              response.OrganizationDetails.Value().AdminDetails.Value().emplace_back(
                  std::move(vectorItem));
            }
          }
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::IssuerAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::IssuerBundle>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::IssuerBundle>
KeyVaultClient::DeleteCertificateIssuer(const std::string& issuerName, const Core::Context& context)
    const
{
  auto url = m_url;
  url.AppendPath("certificates/issuers/");
  if (issuerName.empty())
  {
    throw std::invalid_argument("Parameter 'issuerName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(issuerName));

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Delete, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::IssuerBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("provider") && !jsonRoot["provider"].is_null())
        {
          response.Provider = jsonRoot["provider"].get<std::string>();
        }

        if (jsonRoot.contains("credentials") && !jsonRoot["credentials"].is_null())
        {
          response.Credentials = Models::IssuerCredentials{};

          if (jsonRoot["credentials"].contains("account_id")
              && !jsonRoot["credentials"]["account_id"].is_null())
          {
            response.Credentials.Value().AccountId
                = jsonRoot["credentials"]["account_id"].get<std::string>();
          }

          if (jsonRoot["credentials"].contains("pwd") && !jsonRoot["credentials"]["pwd"].is_null())
          {
            response.Credentials.Value().Password
                = jsonRoot["credentials"]["pwd"].get<std::string>();
          }
        }

        if (jsonRoot.contains("org_details") && !jsonRoot["org_details"].is_null())
        {
          response.OrganizationDetails = Models::OrganizationDetails{};

          if (jsonRoot["org_details"].contains("id") && !jsonRoot["org_details"]["id"].is_null())
          {
            response.OrganizationDetails.Value().Id
                = jsonRoot["org_details"]["id"].get<std::string>();
          }

          if (jsonRoot["org_details"].contains("admin_details")
              && !jsonRoot["org_details"]["admin_details"].is_null())
          {
            response.OrganizationDetails.Value().AdminDetails
                = std::vector<Models::AdministratorDetails>{};

            for (auto const& jsonItem : jsonRoot["org_details"]["admin_details"])
            {
              Models::AdministratorDetails vectorItem{};

              if (jsonItem.contains("first_name") && !jsonItem["first_name"].is_null())
              {
                vectorItem.FirstName = jsonItem["first_name"].get<std::string>();
              }

              if (jsonItem.contains("last_name") && !jsonItem["last_name"].is_null())
              {
                vectorItem.LastName = jsonItem["last_name"].get<std::string>();
              }

              if (jsonItem.contains("email") && !jsonItem["email"].is_null())
              {
                vectorItem.EmailAddress = jsonItem["email"].get<std::string>();
              }

              if (jsonItem.contains("phone") && !jsonItem["phone"].is_null())
              {
                vectorItem.Phone = jsonItem["phone"].get<std::string>();
              }

              response.OrganizationDetails.Value().AdminDetails.Value().emplace_back(
                  std::move(vectorItem));
            }
          }
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::IssuerAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::IssuerBundle>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateOperation>
KeyVaultClient::CreateCertificate(
    const std::string& certificateName,
    const Models::CertificateCreateParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("create");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    if (parameters.CertificatePolicy.HasValue())
    {
      if (parameters.CertificatePolicy.Value().Id.HasValue())
      {
        jsonRoot["policy"]["id"] = parameters.CertificatePolicy.Value().Id.Value();
      }

      if (parameters.CertificatePolicy.Value().KeyProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value().KeyProperties.Value().Exportable.HasValue())
        {
          jsonRoot["policy"]["key_props"]["exportable"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().Exportable.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().KeyType.HasValue())
        {
          jsonRoot["policy"]["key_props"]["kty"] = parameters.CertificatePolicy.Value()
                                                       .KeyProperties.Value()
                                                       .KeyType.Value()
                                                       .ToString();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().KeySize.HasValue())
        {
          jsonRoot["policy"]["key_props"]["key_size"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().KeySize.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().ReuseKey.HasValue())
        {
          jsonRoot["policy"]["key_props"]["reuse_key"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().ReuseKey.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().Curve.HasValue())
        {
          jsonRoot["policy"]["key_props"]["crv"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().Curve.Value().ToString();
        }
      }

      if (parameters.CertificatePolicy.Value().SecretProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value().SecretProperties.Value().ContentType.HasValue())
        {
          jsonRoot["policy"]["secret_props"]["contentType"]
              = parameters.CertificatePolicy.Value().SecretProperties.Value().ContentType.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().X509CertificateProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .Subject.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["subject"] = parameters.CertificatePolicy.Value()
                                                            .X509CertificateProperties.Value()
                                                            .Subject.Value();
        }

        if (parameters.CertificatePolicy.Value().X509CertificateProperties.Value().Ekus.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["ekus"] = Core::Json::_internal::json::array();

          const size_t size = parameters.CertificatePolicy.Value()
                                  .X509CertificateProperties.Value()
                                  .Ekus.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["policy"]["x509_props"]["ekus"][i] = parameters.CertificatePolicy.Value()
                                                              .X509CertificateProperties.Value()
                                                              .Ekus.Value()[i];
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .SubjectAlternativeNames.HasValue())
        {
          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .Emails.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["emails"]
                = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .Emails.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["emails"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .Emails.Value()[i];
            }
          }

          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .DnsNames.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["dns_names"]
                = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .DnsNames.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["dns_names"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .DnsNames.Value()[i];
            }
          }

          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .Upns.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["upns"] = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .Upns.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["upns"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .Upns.Value()[i];
            }
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .KeyUsage.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["key_usage"] = Core::Json::_internal::json::array();

          const size_t size = parameters.CertificatePolicy.Value()
                                  .X509CertificateProperties.Value()
                                  .KeyUsage.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["policy"]["x509_props"]["key_usage"][i]
                = parameters.CertificatePolicy.Value()
                      .X509CertificateProperties.Value()
                      .KeyUsage.Value()[i]
                      .ToString();
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .ValidityInMonths.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["validity_months"]
              = parameters.CertificatePolicy.Value()
                    .X509CertificateProperties.Value()
                    .ValidityInMonths.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().LifetimeActions.HasValue())
      {
        jsonRoot["policy"]["lifetime_actions"] = Core::Json::_internal::json::array();

        const size_t size = parameters.CertificatePolicy.Value().LifetimeActions.Value().size();
        for (size_t i = 0; i < size; ++i)
        {
          if (parameters.CertificatePolicy.Value().LifetimeActions.Value()[i].Trigger.HasValue())
          {
            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Trigger.Value()
                    .LifetimePercentage.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["trigger"]["lifetime_percentage"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Trigger.Value()
                        .LifetimePercentage.Value();
            }

            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Trigger.Value()
                    .DaysBeforeExpiry.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["trigger"]["days_before_expiry"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Trigger.Value()
                        .DaysBeforeExpiry.Value();
            }
          }

          if (parameters.CertificatePolicy.Value().LifetimeActions.Value()[i].Action.HasValue())
          {
            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Action.Value()
                    .ActionType.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["action"]["action_type"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Action.Value()
                        .ActionType.Value()
                        .ToString();
            }
          }
        }
      }

      if (parameters.CertificatePolicy.Value().IssuerParameters.HasValue())
      {
        if (parameters.CertificatePolicy.Value().IssuerParameters.Value().Name.HasValue())
        {
          jsonRoot["policy"]["issuer"]["name"]
              = parameters.CertificatePolicy.Value().IssuerParameters.Value().Name.Value();
        }

        if (parameters.CertificatePolicy.Value()
                .IssuerParameters.Value()
                .CertificateType.HasValue())
        {
          jsonRoot["policy"]["issuer"]["cty"] = parameters.CertificatePolicy.Value()
                                                    .IssuerParameters.Value()
                                                    .CertificateType.Value();
        }

        if (parameters.CertificatePolicy.Value()
                .IssuerParameters.Value()
                .CertificateTransparency.HasValue())
        {
          jsonRoot["policy"]["issuer"]["cert_transparency"] = parameters.CertificatePolicy.Value()
                                                                  .IssuerParameters.Value()
                                                                  .CertificateTransparency.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().Attributes.HasValue())
      {
        if (parameters.CertificatePolicy.Value().Attributes.Value().Enabled.HasValue())
        {
          jsonRoot["policy"]["attributes"]["enabled"]
              = parameters.CertificatePolicy.Value().Attributes.Value().Enabled.Value();
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().NotBefore.HasValue())
        {
          jsonRoot["policy"]["attributes"]["nbf"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().NotBefore.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Expires.HasValue())
        {
          jsonRoot["policy"]["attributes"]["exp"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Expires.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Created.HasValue())
        {
          jsonRoot["policy"]["attributes"]["created"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Created.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Updated.HasValue())
        {
          jsonRoot["policy"]["attributes"]["updated"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Updated.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().RecoverableDays.HasValue())
        {
          jsonRoot["policy"]["attributes"]["recoverableDays"]
              = parameters.CertificatePolicy.Value().Attributes.Value().RecoverableDays.Value();
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().RecoveryLevel.HasValue())
        {
          jsonRoot["policy"]["attributes"]["recoveryLevel"] = parameters.CertificatePolicy.Value()
                                                                  .Attributes.Value()
                                                                  .RecoveryLevel.Value()
                                                                  .ToString();
        }
      }
    }

    if (parameters.CertificateAttributes.HasValue())
    {
      if (parameters.CertificateAttributes.Value().Enabled.HasValue())
      {
        jsonRoot["attributes"]["enabled"]
            = parameters.CertificateAttributes.Value().Enabled.Value();
      }

      if (parameters.CertificateAttributes.Value().NotBefore.HasValue())
      {
        jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            parameters.CertificateAttributes.Value().NotBefore.Value());
      }

      if (parameters.CertificateAttributes.Value().Expires.HasValue())
      {
        jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            parameters.CertificateAttributes.Value().Expires.Value());
      }

      if (parameters.CertificateAttributes.Value().Created.HasValue())
      {
        jsonRoot["attributes"]["created"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameters.CertificateAttributes.Value().Created.Value());
      }

      if (parameters.CertificateAttributes.Value().Updated.HasValue())
      {
        jsonRoot["attributes"]["updated"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameters.CertificateAttributes.Value().Updated.Value());
      }

      if (parameters.CertificateAttributes.Value().RecoverableDays.HasValue())
      {
        jsonRoot["attributes"]["recoverableDays"]
            = parameters.CertificateAttributes.Value().RecoverableDays.Value();
      }

      if (parameters.CertificateAttributes.Value().RecoveryLevel.HasValue())
      {
        jsonRoot["attributes"]["recoveryLevel"]
            = parameters.CertificateAttributes.Value().RecoveryLevel.Value().ToString();
      }
    }

    if (parameters.Tags.HasValue())
    {
      jsonRoot["tags"] = Core::Json::_internal::json::object();

      for (auto const& kv : parameters.Tags.Value())
      {
        jsonRoot["tags"][kv.first] = kv.second;
      }
    }

    if (parameters.PreserveCertOrder.HasValue())
    {
      jsonRoot["preserveCertOrder"] = parameters.PreserveCertOrder.Value();
    }

    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Accepted)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateOperation response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("issuer") && !jsonRoot["issuer"].is_null())
        {
          response.IssuerParameters = Models::IssuerParameters{};

          if (jsonRoot["issuer"].contains("name") && !jsonRoot["issuer"]["name"].is_null())
          {
            response.IssuerParameters.Value().Name = jsonRoot["issuer"]["name"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cty") && !jsonRoot["issuer"]["cty"].is_null())
          {
            response.IssuerParameters.Value().CertificateType
                = jsonRoot["issuer"]["cty"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cert_transparency")
              && !jsonRoot["issuer"]["cert_transparency"].is_null())
          {
            response.IssuerParameters.Value().CertificateTransparency
                = jsonRoot["issuer"]["cert_transparency"].get<bool>();
          }
        }

        if (jsonRoot.contains("csr") && !jsonRoot["csr"].is_null())
        {
          response.Csr = Core::Convert::Base64Decode(jsonRoot["csr"].get<std::string>());
        }

        if (jsonRoot.contains("cancellation_requested")
            && !jsonRoot["cancellation_requested"].is_null())
        {
          response.CancellationRequested = jsonRoot["cancellation_requested"].get<bool>();
        }

        if (jsonRoot.contains("status") && !jsonRoot["status"].is_null())
        {
          response.Status = jsonRoot["status"].get<std::string>();
        }

        if (jsonRoot.contains("status_details") && !jsonRoot["status_details"].is_null())
        {
          response.StatusDetails = jsonRoot["status_details"].get<std::string>();
        }

        const std::function<void(Models::KeyVaultErrorError&, Core::Json::_internal::json const&)>
            deserializeKeyVaultErrorError = [&](Models::KeyVaultErrorError& keyVaultErrorError,
                                                Core::Json::_internal::json const& jsonItem) {
              if (jsonItem.contains("code") && !jsonItem["code"].is_null())
              {
                keyVaultErrorError.Code = jsonItem["code"].get<std::string>();
              }

              if (jsonItem.contains("message") && !jsonItem["message"].is_null())
              {
                keyVaultErrorError.Message = jsonItem["message"].get<std::string>();
              }

              const std::function<void(
                  std::shared_ptr<Models::KeyVaultErrorError>&, Core::Json::_internal::json const&)>
                  deserializeKeyVaultErrorErrorPtr
                  = [&](std::shared_ptr<Models::KeyVaultErrorError>& keyVaultErrorError,
                        Core::Json::_internal::json const& jsonItem) {
                      if (jsonItem.contains("code") && !jsonItem["code"].is_null())
                      {
                        if (!keyVaultErrorError)
                        {
                          keyVaultErrorError = std::make_shared<Models::KeyVaultErrorError>();
                        }

                        keyVaultErrorError->Code = jsonItem["code"].get<std::string>();
                      }

                      if (jsonItem.contains("message") && !jsonItem["message"].is_null())
                      {
                        if (!keyVaultErrorError)
                        {
                          keyVaultErrorError = std::make_shared<Models::KeyVaultErrorError>();
                        }

                        keyVaultErrorError->Message = jsonItem["message"].get<std::string>();
                      }

                      deserializeKeyVaultErrorErrorPtr(
                          keyVaultErrorError->InnerError, jsonItem["innererror"]);
                    };
              deserializeKeyVaultErrorErrorPtr(
                  keyVaultErrorError.InnerError, jsonItem["innererror"]);
            };
        if (jsonRoot.contains("error") && !jsonRoot["error"].is_null())
        {
          response.Error = Models::KeyVaultErrorError{};
          deserializeKeyVaultErrorError(response.Error.Value(), jsonRoot["error"]);
        }

        if (jsonRoot.contains("target") && !jsonRoot["target"].is_null())
        {
          response.Target = jsonRoot["target"].get<std::string>();
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }

        if (jsonRoot.contains("request_id") && !jsonRoot["request_id"].is_null())
        {
          response.RequestId = jsonRoot["request_id"].get<std::string>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateOperation>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateBundle>
KeyVaultClient::ImportCertificate(
    const std::string& certificateName,
    const Models::CertificateImportParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("import");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["value"] = parameters.Base64EncodedCertificate;
    if (parameters.Password.HasValue())
    {
      jsonRoot["pwd"] = parameters.Password.Value();
    }

    if (parameters.CertificatePolicy.HasValue())
    {
      if (parameters.CertificatePolicy.Value().Id.HasValue())
      {
        jsonRoot["policy"]["id"] = parameters.CertificatePolicy.Value().Id.Value();
      }

      if (parameters.CertificatePolicy.Value().KeyProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value().KeyProperties.Value().Exportable.HasValue())
        {
          jsonRoot["policy"]["key_props"]["exportable"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().Exportable.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().KeyType.HasValue())
        {
          jsonRoot["policy"]["key_props"]["kty"] = parameters.CertificatePolicy.Value()
                                                       .KeyProperties.Value()
                                                       .KeyType.Value()
                                                       .ToString();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().KeySize.HasValue())
        {
          jsonRoot["policy"]["key_props"]["key_size"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().KeySize.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().ReuseKey.HasValue())
        {
          jsonRoot["policy"]["key_props"]["reuse_key"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().ReuseKey.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().Curve.HasValue())
        {
          jsonRoot["policy"]["key_props"]["crv"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().Curve.Value().ToString();
        }
      }

      if (parameters.CertificatePolicy.Value().SecretProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value().SecretProperties.Value().ContentType.HasValue())
        {
          jsonRoot["policy"]["secret_props"]["contentType"]
              = parameters.CertificatePolicy.Value().SecretProperties.Value().ContentType.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().X509CertificateProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .Subject.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["subject"] = parameters.CertificatePolicy.Value()
                                                            .X509CertificateProperties.Value()
                                                            .Subject.Value();
        }

        if (parameters.CertificatePolicy.Value().X509CertificateProperties.Value().Ekus.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["ekus"] = Core::Json::_internal::json::array();

          const size_t size = parameters.CertificatePolicy.Value()
                                  .X509CertificateProperties.Value()
                                  .Ekus.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["policy"]["x509_props"]["ekus"][i] = parameters.CertificatePolicy.Value()
                                                              .X509CertificateProperties.Value()
                                                              .Ekus.Value()[i];
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .SubjectAlternativeNames.HasValue())
        {
          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .Emails.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["emails"]
                = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .Emails.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["emails"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .Emails.Value()[i];
            }
          }

          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .DnsNames.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["dns_names"]
                = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .DnsNames.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["dns_names"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .DnsNames.Value()[i];
            }
          }

          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .Upns.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["upns"] = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .Upns.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["upns"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .Upns.Value()[i];
            }
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .KeyUsage.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["key_usage"] = Core::Json::_internal::json::array();

          const size_t size = parameters.CertificatePolicy.Value()
                                  .X509CertificateProperties.Value()
                                  .KeyUsage.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["policy"]["x509_props"]["key_usage"][i]
                = parameters.CertificatePolicy.Value()
                      .X509CertificateProperties.Value()
                      .KeyUsage.Value()[i]
                      .ToString();
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .ValidityInMonths.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["validity_months"]
              = parameters.CertificatePolicy.Value()
                    .X509CertificateProperties.Value()
                    .ValidityInMonths.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().LifetimeActions.HasValue())
      {
        jsonRoot["policy"]["lifetime_actions"] = Core::Json::_internal::json::array();

        const size_t size = parameters.CertificatePolicy.Value().LifetimeActions.Value().size();
        for (size_t i = 0; i < size; ++i)
        {
          if (parameters.CertificatePolicy.Value().LifetimeActions.Value()[i].Trigger.HasValue())
          {
            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Trigger.Value()
                    .LifetimePercentage.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["trigger"]["lifetime_percentage"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Trigger.Value()
                        .LifetimePercentage.Value();
            }

            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Trigger.Value()
                    .DaysBeforeExpiry.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["trigger"]["days_before_expiry"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Trigger.Value()
                        .DaysBeforeExpiry.Value();
            }
          }

          if (parameters.CertificatePolicy.Value().LifetimeActions.Value()[i].Action.HasValue())
          {
            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Action.Value()
                    .ActionType.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["action"]["action_type"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Action.Value()
                        .ActionType.Value()
                        .ToString();
            }
          }
        }
      }

      if (parameters.CertificatePolicy.Value().IssuerParameters.HasValue())
      {
        if (parameters.CertificatePolicy.Value().IssuerParameters.Value().Name.HasValue())
        {
          jsonRoot["policy"]["issuer"]["name"]
              = parameters.CertificatePolicy.Value().IssuerParameters.Value().Name.Value();
        }

        if (parameters.CertificatePolicy.Value()
                .IssuerParameters.Value()
                .CertificateType.HasValue())
        {
          jsonRoot["policy"]["issuer"]["cty"] = parameters.CertificatePolicy.Value()
                                                    .IssuerParameters.Value()
                                                    .CertificateType.Value();
        }

        if (parameters.CertificatePolicy.Value()
                .IssuerParameters.Value()
                .CertificateTransparency.HasValue())
        {
          jsonRoot["policy"]["issuer"]["cert_transparency"] = parameters.CertificatePolicy.Value()
                                                                  .IssuerParameters.Value()
                                                                  .CertificateTransparency.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().Attributes.HasValue())
      {
        if (parameters.CertificatePolicy.Value().Attributes.Value().Enabled.HasValue())
        {
          jsonRoot["policy"]["attributes"]["enabled"]
              = parameters.CertificatePolicy.Value().Attributes.Value().Enabled.Value();
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().NotBefore.HasValue())
        {
          jsonRoot["policy"]["attributes"]["nbf"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().NotBefore.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Expires.HasValue())
        {
          jsonRoot["policy"]["attributes"]["exp"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Expires.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Created.HasValue())
        {
          jsonRoot["policy"]["attributes"]["created"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Created.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Updated.HasValue())
        {
          jsonRoot["policy"]["attributes"]["updated"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Updated.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().RecoverableDays.HasValue())
        {
          jsonRoot["policy"]["attributes"]["recoverableDays"]
              = parameters.CertificatePolicy.Value().Attributes.Value().RecoverableDays.Value();
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().RecoveryLevel.HasValue())
        {
          jsonRoot["policy"]["attributes"]["recoveryLevel"] = parameters.CertificatePolicy.Value()
                                                                  .Attributes.Value()
                                                                  .RecoveryLevel.Value()
                                                                  .ToString();
        }
      }
    }

    if (parameters.CertificateAttributes.HasValue())
    {
      if (parameters.CertificateAttributes.Value().Enabled.HasValue())
      {
        jsonRoot["attributes"]["enabled"]
            = parameters.CertificateAttributes.Value().Enabled.Value();
      }

      if (parameters.CertificateAttributes.Value().NotBefore.HasValue())
      {
        jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            parameters.CertificateAttributes.Value().NotBefore.Value());
      }

      if (parameters.CertificateAttributes.Value().Expires.HasValue())
      {
        jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            parameters.CertificateAttributes.Value().Expires.Value());
      }

      if (parameters.CertificateAttributes.Value().Created.HasValue())
      {
        jsonRoot["attributes"]["created"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameters.CertificateAttributes.Value().Created.Value());
      }

      if (parameters.CertificateAttributes.Value().Updated.HasValue())
      {
        jsonRoot["attributes"]["updated"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameters.CertificateAttributes.Value().Updated.Value());
      }

      if (parameters.CertificateAttributes.Value().RecoverableDays.HasValue())
      {
        jsonRoot["attributes"]["recoverableDays"]
            = parameters.CertificateAttributes.Value().RecoverableDays.Value();
      }

      if (parameters.CertificateAttributes.Value().RecoveryLevel.HasValue())
      {
        jsonRoot["attributes"]["recoveryLevel"]
            = parameters.CertificateAttributes.Value().RecoveryLevel.Value().ToString();
      }
    }

    if (parameters.Tags.HasValue())
    {
      jsonRoot["tags"] = Core::Json::_internal::json::object();

      for (auto const& kv : parameters.Tags.Value())
      {
        jsonRoot["tags"][kv.first] = kv.second;
      }
    }

    if (parameters.PreserveCertOrder.HasValue())
    {
      jsonRoot["preserveCertOrder"] = parameters.PreserveCertOrder.Value();
    }

    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

        if (jsonRoot.contains("sid") && !jsonRoot["sid"].is_null())
        {
          response.Sid = jsonRoot["sid"].get<std::string>();
        }

        if (jsonRoot.contains("x5t") && !jsonRoot["x5t"].is_null())
        {
          response.X509Thumbprint
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["x5t"].get<std::string>());
        }

        if (jsonRoot.contains("policy") && !jsonRoot["policy"].is_null())
        {
          response.Policy = Models::CertificatePolicy{};

          if (jsonRoot["policy"].contains("id") && !jsonRoot["policy"]["id"].is_null())
          {
            response.Policy.Value().Id = jsonRoot["policy"]["id"].get<std::string>();
          }

          if (jsonRoot["policy"].contains("key_props")
              && !jsonRoot["policy"]["key_props"].is_null())
          {
            response.Policy.Value().KeyProperties = Models::KeyProperties{};

            if (jsonRoot["policy"]["key_props"].contains("exportable")
                && !jsonRoot["policy"]["key_props"]["exportable"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Exportable
                  = jsonRoot["policy"]["key_props"]["exportable"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("kty")
                && !jsonRoot["policy"]["key_props"]["kty"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeyType = Models::JsonWebKeyType(
                  jsonRoot["policy"]["key_props"]["kty"].get<std::string>());
            }

            if (jsonRoot["policy"]["key_props"].contains("key_size")
                && !jsonRoot["policy"]["key_props"]["key_size"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeySize
                  = jsonRoot["policy"]["key_props"]["key_size"].is_string()
                  ? std::stoi(jsonRoot["policy"]["key_props"]["key_size"].get<std::string>())
                  : jsonRoot["policy"]["key_props"]["key_size"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["key_props"].contains("reuse_key")
                && !jsonRoot["policy"]["key_props"]["reuse_key"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().ReuseKey
                  = jsonRoot["policy"]["key_props"]["reuse_key"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("crv")
                && !jsonRoot["policy"]["key_props"]["crv"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Curve = Models::JsonWebKeyCurveName(
                  jsonRoot["policy"]["key_props"]["crv"].get<std::string>());
            }
          }

          if (jsonRoot["policy"].contains("secret_props")
              && !jsonRoot["policy"]["secret_props"].is_null())
          {
            response.Policy.Value().SecretProperties = Models::SecretProperties{};

            if (jsonRoot["policy"]["secret_props"].contains("contentType")
                && !jsonRoot["policy"]["secret_props"]["contentType"].is_null())
            {
              response.Policy.Value().SecretProperties.Value().ContentType
                  = jsonRoot["policy"]["secret_props"]["contentType"].get<std::string>();
            }
          }

          if (jsonRoot["policy"].contains("x509_props")
              && !jsonRoot["policy"]["x509_props"].is_null())
          {
            response.Policy.Value().X509CertificateProperties = Models::X509CertificateProperties{};

            if (jsonRoot["policy"]["x509_props"].contains("subject")
                && !jsonRoot["policy"]["x509_props"]["subject"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Subject
                  = jsonRoot["policy"]["x509_props"]["subject"].get<std::string>();
            }

            if (jsonRoot["policy"]["x509_props"].contains("ekus")
                && !jsonRoot["policy"]["x509_props"]["ekus"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Ekus
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["ekus"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.Policy.Value().X509CertificateProperties.Value().Ekus.Value().emplace_back(
                    std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("sans")
                && !jsonRoot["policy"]["x509_props"]["sans"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().SubjectAlternativeNames
                  = Models::SubjectAlternativeNames{};

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("emails")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["emails"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["emails"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("dns_names")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["dns_names"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["dns_names"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("upns")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["upns"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["upns"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("key_usage")
                && !jsonRoot["policy"]["x509_props"]["key_usage"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().KeyUsage
                  = std::vector<Models::KeyUsageType>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["key_usage"])
              {
                Models::KeyUsageType vectorItem{};

                vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .KeyUsage.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("validity_months")
                && !jsonRoot["policy"]["x509_props"]["validity_months"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().ValidityInMonths
                  = jsonRoot["policy"]["x509_props"]["validity_months"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["x509_props"]["validity_months"].get<std::string>())
                  : jsonRoot["policy"]["x509_props"]["validity_months"].get<std::int32_t>();
            }
          }

          if (jsonRoot["policy"].contains("lifetime_actions")
              && !jsonRoot["policy"]["lifetime_actions"].is_null())
          {
            response.Policy.Value().LifetimeActions = std::vector<Models::LifetimeAction>{};

            for (auto const& jsonItem : jsonRoot["policy"]["lifetime_actions"])
            {
              Models::LifetimeAction vectorItem{};

              if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
              {
                vectorItem.Trigger = Models::Trigger{};

                if (jsonItem["trigger"].contains("lifetime_percentage")
                    && !jsonItem["trigger"]["lifetime_percentage"].is_null())
                {
                  vectorItem.Trigger.Value().LifetimePercentage
                      = jsonItem["trigger"]["lifetime_percentage"].is_string()
                      ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                      : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
                }

                if (jsonItem["trigger"].contains("days_before_expiry")
                    && !jsonItem["trigger"]["days_before_expiry"].is_null())
                {
                  vectorItem.Trigger.Value().DaysBeforeExpiry
                      = jsonItem["trigger"]["days_before_expiry"].is_string()
                      ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                      : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
                }
              }

              if (jsonItem.contains("action") && !jsonItem["action"].is_null())
              {
                vectorItem.Action = Models::Action{};

                if (jsonItem["action"].contains("action_type")
                    && !jsonItem["action"]["action_type"].is_null())
                {
                  vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                      jsonItem["action"]["action_type"].get<std::string>());
                }
              }

              response.Policy.Value().LifetimeActions.Value().emplace_back(std::move(vectorItem));
            }
          }

          if (jsonRoot["policy"].contains("issuer") && !jsonRoot["policy"]["issuer"].is_null())
          {
            response.Policy.Value().IssuerParameters = Models::IssuerParameters{};

            if (jsonRoot["policy"]["issuer"].contains("name")
                && !jsonRoot["policy"]["issuer"]["name"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().Name
                  = jsonRoot["policy"]["issuer"]["name"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cty")
                && !jsonRoot["policy"]["issuer"]["cty"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateType
                  = jsonRoot["policy"]["issuer"]["cty"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cert_transparency")
                && !jsonRoot["policy"]["issuer"]["cert_transparency"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateTransparency
                  = jsonRoot["policy"]["issuer"]["cert_transparency"].get<bool>();
            }
          }

          if (jsonRoot["policy"].contains("attributes")
              && !jsonRoot["policy"]["attributes"].is_null())
          {
            response.Policy.Value().Attributes = Models::CertificateAttributes{};

            if (jsonRoot["policy"]["attributes"].contains("enabled")
                && !jsonRoot["policy"]["attributes"]["enabled"].is_null())
            {
              response.Policy.Value().Attributes.Value().Enabled
                  = jsonRoot["policy"]["attributes"]["enabled"].get<bool>();
            }

            if (jsonRoot["policy"]["attributes"].contains("nbf")
                && !jsonRoot["policy"]["attributes"]["nbf"].is_null())
            {
              response.Policy.Value().Attributes.Value().NotBefore
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["nbf"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["nbf"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["nbf"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("exp")
                && !jsonRoot["policy"]["attributes"]["exp"].is_null())
            {
              response.Policy.Value().Attributes.Value().Expires
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["exp"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["exp"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["exp"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("created")
                && !jsonRoot["policy"]["attributes"]["created"].is_null())
            {
              response.Policy.Value().Attributes.Value().Created
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["created"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["created"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["created"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("updated")
                && !jsonRoot["policy"]["attributes"]["updated"].is_null())
            {
              response.Policy.Value().Attributes.Value().Updated
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["updated"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["updated"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["updated"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("recoverableDays")
                && !jsonRoot["policy"]["attributes"]["recoverableDays"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoverableDays
                  = jsonRoot["policy"]["attributes"]["recoverableDays"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::string>())
                  : jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["attributes"].contains("recoveryLevel")
                && !jsonRoot["policy"]["attributes"]["recoveryLevel"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoveryLevel
                  = Models::DeletionRecoveryLevel(
                      jsonRoot["policy"]["attributes"]["recoveryLevel"].get<std::string>());
            }
          }
        }

        if (jsonRoot.contains("cer") && !jsonRoot["cer"].is_null())
        {
          response.Cer = Core::Convert::Base64Decode(jsonRoot["cer"].get<std::string>());
        }

        if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null())
        {
          response.ContentType = jsonRoot["contentType"].get<std::string>();
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }

        if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null())
        {
          response.Tags = std::map<std::string, std::string>{};

          for (auto const& kv : jsonRoot["tags"].items())
          {
            std::string value{};
            value = kv.value().get<std::string>();
            response.Tags.Value().emplace(kv.key(), value);
          }
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateBundle>(std::move(response), std::move(rawResponse));
}

GetCertificateVersionsPagedResponse KeyVaultClient::GetCertificateVersions(
    const std::string& certificateName,
    const KeyVaultClientGetCertificateVersionsOptions& options,
    const Core::Context& context) const
{
  Core::Url url;
  if (options.NextPageToken.empty())
  {
    url = m_url;
    url.AppendPath("certificates/");
    if (certificateName.empty())
    {
      throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
    }
    url.AppendPath(Core::Url::Encode(certificateName));
    url.AppendPath("versions");

    url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));
    if (options.Maxresults.HasValue())
    {
      url.AppendQueryParameter("maxresults", std::to_string(options.Maxresults.Value()));
    }
  }
  else
  {
    if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0)
    {
      url = Core::Url(options.NextPageToken);
      if (url.GetPort() == 0 && m_url.GetPort() != 0 && url.GetHost() == m_url.GetHost())
      {
        url.SetPort(m_url.GetPort());
      }
    }
    else
    {
      url = Core::Url(
          m_url.GetScheme() + "://" + m_url.GetHost() + ':' + std::to_string(m_url.GetPort()) + '/'
          + (options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1)
                                             : options.NextPageToken));
    }

    const auto qps = url.GetQueryParameters();
    if (qps.find("api-version") != qps.cend())
    {
      url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));
    }
  }

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  GetCertificateVersionsPagedResponse response{};
  response.m_client = std::make_shared<KeyVaultClient>(*this);
  response.m_certificateName = certificateName;
  response.m_options = options;
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());
        if (jsonRoot.contains("nextLink") && !jsonRoot["nextLink"].is_null())
        {
          response.NextPageToken = jsonRoot["nextLink"].get<std::string>();
        }

        if (jsonRoot.contains("value") && !jsonRoot["value"].is_null())
        {
          response.Value = std::vector<Models::CertificateItem>{};

          for (auto const& jsonItem : jsonRoot["value"])
          {
            Models::CertificateItem vectorItem{};

            if (jsonItem.contains("id") && !jsonItem["id"].is_null())
            {
              vectorItem.Id = jsonItem["id"].get<std::string>();
            }

            if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null())
            {
              vectorItem.Attributes = Models::CertificateAttributes{};

              if (jsonItem["attributes"].contains("enabled")
                  && !jsonItem["attributes"]["enabled"].is_null())
              {
                vectorItem.Attributes.Value().Enabled
                    = jsonItem["attributes"]["enabled"].get<bool>();
              }

              if (jsonItem["attributes"].contains("nbf")
                  && !jsonItem["attributes"]["nbf"].is_null())
              {
                vectorItem.Attributes.Value().NotBefore
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["nbf"].is_string()
                            ? std::stoll(jsonItem["attributes"]["nbf"].get<std::string>())
                            : jsonItem["attributes"]["nbf"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("exp")
                  && !jsonItem["attributes"]["exp"].is_null())
              {
                vectorItem.Attributes.Value().Expires
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["exp"].is_string()
                            ? std::stoll(jsonItem["attributes"]["exp"].get<std::string>())
                            : jsonItem["attributes"]["exp"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("created")
                  && !jsonItem["attributes"]["created"].is_null())
              {
                vectorItem.Attributes.Value().Created
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["created"].is_string()
                            ? std::stoll(jsonItem["attributes"]["created"].get<std::string>())
                            : jsonItem["attributes"]["created"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("updated")
                  && !jsonItem["attributes"]["updated"].is_null())
              {
                vectorItem.Attributes.Value().Updated
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["updated"].is_string()
                            ? std::stoll(jsonItem["attributes"]["updated"].get<std::string>())
                            : jsonItem["attributes"]["updated"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("recoverableDays")
                  && !jsonItem["attributes"]["recoverableDays"].is_null())
              {
                vectorItem.Attributes.Value().RecoverableDays
                    = jsonItem["attributes"]["recoverableDays"].is_string()
                    ? std::stoi(jsonItem["attributes"]["recoverableDays"].get<std::string>())
                    : jsonItem["attributes"]["recoverableDays"].get<std::int32_t>();
              }

              if (jsonItem["attributes"].contains("recoveryLevel")
                  && !jsonItem["attributes"]["recoveryLevel"].is_null())
              {
                vectorItem.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                    jsonItem["attributes"]["recoveryLevel"].get<std::string>());
              }
            }

            if (jsonItem.contains("tags") && !jsonItem["tags"].is_null())
            {
              vectorItem.Tags = std::map<std::string, std::string>{};

              for (auto const& kv : jsonItem["tags"].items())
              {
                std::string value{};
                value = kv.value().get<std::string>();
                vectorItem.Tags.Value().emplace(kv.key(), value);
              }
            }

            if (jsonItem.contains("x5t") && !jsonItem["x5t"].is_null())
            {
              vectorItem.X509Thumbprint
                  = Core::_internal::Base64Url::Base64UrlDecode(jsonItem["x5t"].get<std::string>());
            }

            response.Value.Value().emplace_back(std::move(vectorItem));
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  response.RawResponse = std::move(rawResponse);

  return response;
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificatePolicy>
KeyVaultClient::GetCertificatePolicy(
    const std::string& certificateName,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("policy");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificatePolicy response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("key_props") && !jsonRoot["key_props"].is_null())
        {
          response.KeyProperties = Models::KeyProperties{};

          if (jsonRoot["key_props"].contains("exportable")
              && !jsonRoot["key_props"]["exportable"].is_null())
          {
            response.KeyProperties.Value().Exportable
                = jsonRoot["key_props"]["exportable"].get<bool>();
          }

          if (jsonRoot["key_props"].contains("kty") && !jsonRoot["key_props"]["kty"].is_null())
          {
            response.KeyProperties.Value().KeyType
                = Models::JsonWebKeyType(jsonRoot["key_props"]["kty"].get<std::string>());
          }

          if (jsonRoot["key_props"].contains("key_size")
              && !jsonRoot["key_props"]["key_size"].is_null())
          {
            response.KeyProperties.Value().KeySize = jsonRoot["key_props"]["key_size"].is_string()
                ? std::stoi(jsonRoot["key_props"]["key_size"].get<std::string>())
                : jsonRoot["key_props"]["key_size"].get<std::int32_t>();
          }

          if (jsonRoot["key_props"].contains("reuse_key")
              && !jsonRoot["key_props"]["reuse_key"].is_null())
          {
            response.KeyProperties.Value().ReuseKey
                = jsonRoot["key_props"]["reuse_key"].get<bool>();
          }

          if (jsonRoot["key_props"].contains("crv") && !jsonRoot["key_props"]["crv"].is_null())
          {
            response.KeyProperties.Value().Curve
                = Models::JsonWebKeyCurveName(jsonRoot["key_props"]["crv"].get<std::string>());
          }
        }

        if (jsonRoot.contains("secret_props") && !jsonRoot["secret_props"].is_null())
        {
          response.SecretProperties = Models::SecretProperties{};

          if (jsonRoot["secret_props"].contains("contentType")
              && !jsonRoot["secret_props"]["contentType"].is_null())
          {
            response.SecretProperties.Value().ContentType
                = jsonRoot["secret_props"]["contentType"].get<std::string>();
          }
        }

        if (jsonRoot.contains("x509_props") && !jsonRoot["x509_props"].is_null())
        {
          response.X509CertificateProperties = Models::X509CertificateProperties{};

          if (jsonRoot["x509_props"].contains("subject")
              && !jsonRoot["x509_props"]["subject"].is_null())
          {
            response.X509CertificateProperties.Value().Subject
                = jsonRoot["x509_props"]["subject"].get<std::string>();
          }

          if (jsonRoot["x509_props"].contains("ekus") && !jsonRoot["x509_props"]["ekus"].is_null())
          {
            response.X509CertificateProperties.Value().Ekus = std::vector<std::string>{};

            for (auto const& jsonItem : jsonRoot["x509_props"]["ekus"])
            {
              std::string vectorItem{};

              vectorItem = jsonItem.get<std::string>();

              response.X509CertificateProperties.Value().Ekus.Value().emplace_back(
                  std::move(vectorItem));
            }
          }

          if (jsonRoot["x509_props"].contains("sans") && !jsonRoot["x509_props"]["sans"].is_null())
          {
            response.X509CertificateProperties.Value().SubjectAlternativeNames
                = Models::SubjectAlternativeNames{};

            if (jsonRoot["x509_props"]["sans"].contains("emails")
                && !jsonRoot["x509_props"]["sans"]["emails"].is_null())
            {
              response.X509CertificateProperties.Value().SubjectAlternativeNames.Value().Emails
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["x509_props"]["sans"]["emails"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["x509_props"]["sans"].contains("dns_names")
                && !jsonRoot["x509_props"]["sans"]["dns_names"].is_null())
            {
              response.X509CertificateProperties.Value().SubjectAlternativeNames.Value().DnsNames
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["x509_props"]["sans"]["dns_names"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["x509_props"]["sans"].contains("upns")
                && !jsonRoot["x509_props"]["sans"]["upns"].is_null())
            {
              response.X509CertificateProperties.Value().SubjectAlternativeNames.Value().Upns
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["x509_props"]["sans"]["upns"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }
          }

          if (jsonRoot["x509_props"].contains("key_usage")
              && !jsonRoot["x509_props"]["key_usage"].is_null())
          {
            response.X509CertificateProperties.Value().KeyUsage
                = std::vector<Models::KeyUsageType>{};

            for (auto const& jsonItem : jsonRoot["x509_props"]["key_usage"])
            {
              Models::KeyUsageType vectorItem{};

              vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

              response.X509CertificateProperties.Value().KeyUsage.Value().emplace_back(
                  std::move(vectorItem));
            }
          }

          if (jsonRoot["x509_props"].contains("validity_months")
              && !jsonRoot["x509_props"]["validity_months"].is_null())
          {
            response.X509CertificateProperties.Value().ValidityInMonths
                = jsonRoot["x509_props"]["validity_months"].is_string()
                ? std::stoi(jsonRoot["x509_props"]["validity_months"].get<std::string>())
                : jsonRoot["x509_props"]["validity_months"].get<std::int32_t>();
          }
        }

        if (jsonRoot.contains("lifetime_actions") && !jsonRoot["lifetime_actions"].is_null())
        {
          response.LifetimeActions = std::vector<Models::LifetimeAction>{};

          for (auto const& jsonItem : jsonRoot["lifetime_actions"])
          {
            Models::LifetimeAction vectorItem{};

            if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
            {
              vectorItem.Trigger = Models::Trigger{};

              if (jsonItem["trigger"].contains("lifetime_percentage")
                  && !jsonItem["trigger"]["lifetime_percentage"].is_null())
              {
                vectorItem.Trigger.Value().LifetimePercentage
                    = jsonItem["trigger"]["lifetime_percentage"].is_string()
                    ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                    : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
              }

              if (jsonItem["trigger"].contains("days_before_expiry")
                  && !jsonItem["trigger"]["days_before_expiry"].is_null())
              {
                vectorItem.Trigger.Value().DaysBeforeExpiry
                    = jsonItem["trigger"]["days_before_expiry"].is_string()
                    ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                    : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
              }
            }

            if (jsonItem.contains("action") && !jsonItem["action"].is_null())
            {
              vectorItem.Action = Models::Action{};

              if (jsonItem["action"].contains("action_type")
                  && !jsonItem["action"]["action_type"].is_null())
              {
                vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                    jsonItem["action"]["action_type"].get<std::string>());
              }
            }

            response.LifetimeActions.Value().emplace_back(std::move(vectorItem));
          }
        }

        if (jsonRoot.contains("issuer") && !jsonRoot["issuer"].is_null())
        {
          response.IssuerParameters = Models::IssuerParameters{};

          if (jsonRoot["issuer"].contains("name") && !jsonRoot["issuer"]["name"].is_null())
          {
            response.IssuerParameters.Value().Name = jsonRoot["issuer"]["name"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cty") && !jsonRoot["issuer"]["cty"].is_null())
          {
            response.IssuerParameters.Value().CertificateType
                = jsonRoot["issuer"]["cty"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cert_transparency")
              && !jsonRoot["issuer"]["cert_transparency"].is_null())
          {
            response.IssuerParameters.Value().CertificateTransparency
                = jsonRoot["issuer"]["cert_transparency"].get<bool>();
          }
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificatePolicy>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificatePolicy>
KeyVaultClient::UpdateCertificatePolicy(
    const std::string& certificateName,
    const Models::CertificatePolicy& certificatePolicy,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("policy");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    if (certificatePolicy.Id.HasValue())
    {
      jsonRoot["id"] = certificatePolicy.Id.Value();
    }

    if (certificatePolicy.KeyProperties.HasValue())
    {
      if (certificatePolicy.KeyProperties.Value().Exportable.HasValue())
      {
        jsonRoot["key_props"]["exportable"]
            = certificatePolicy.KeyProperties.Value().Exportable.Value();
      }

      if (certificatePolicy.KeyProperties.Value().KeyType.HasValue())
      {
        jsonRoot["key_props"]["kty"]
            = certificatePolicy.KeyProperties.Value().KeyType.Value().ToString();
      }

      if (certificatePolicy.KeyProperties.Value().KeySize.HasValue())
      {
        jsonRoot["key_props"]["key_size"] = certificatePolicy.KeyProperties.Value().KeySize.Value();
      }

      if (certificatePolicy.KeyProperties.Value().ReuseKey.HasValue())
      {
        jsonRoot["key_props"]["reuse_key"]
            = certificatePolicy.KeyProperties.Value().ReuseKey.Value();
      }

      if (certificatePolicy.KeyProperties.Value().Curve.HasValue())
      {
        jsonRoot["key_props"]["crv"]
            = certificatePolicy.KeyProperties.Value().Curve.Value().ToString();
      }
    }

    if (certificatePolicy.SecretProperties.HasValue())
    {
      if (certificatePolicy.SecretProperties.Value().ContentType.HasValue())
      {
        jsonRoot["secret_props"]["contentType"]
            = certificatePolicy.SecretProperties.Value().ContentType.Value();
      }
    }

    if (certificatePolicy.X509CertificateProperties.HasValue())
    {
      if (certificatePolicy.X509CertificateProperties.Value().Subject.HasValue())
      {
        jsonRoot["x509_props"]["subject"]
            = certificatePolicy.X509CertificateProperties.Value().Subject.Value();
      }

      if (certificatePolicy.X509CertificateProperties.Value().Ekus.HasValue())
      {
        jsonRoot["x509_props"]["ekus"] = Core::Json::_internal::json::array();

        const size_t size = certificatePolicy.X509CertificateProperties.Value().Ekus.Value().size();
        for (size_t i = 0; i < size; ++i)
        {
          jsonRoot["x509_props"]["ekus"][i]
              = certificatePolicy.X509CertificateProperties.Value().Ekus.Value()[i];
        }
      }

      if (certificatePolicy.X509CertificateProperties.Value().SubjectAlternativeNames.HasValue())
      {
        if (certificatePolicy.X509CertificateProperties.Value()
                .SubjectAlternativeNames.Value()
                .Emails.HasValue())
        {
          jsonRoot["x509_props"]["sans"]["emails"] = Core::Json::_internal::json::array();

          const size_t size = certificatePolicy.X509CertificateProperties.Value()
                                  .SubjectAlternativeNames.Value()
                                  .Emails.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["x509_props"]["sans"]["emails"][i]
                = certificatePolicy.X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()[i];
          }
        }

        if (certificatePolicy.X509CertificateProperties.Value()
                .SubjectAlternativeNames.Value()
                .DnsNames.HasValue())
        {
          jsonRoot["x509_props"]["sans"]["dns_names"] = Core::Json::_internal::json::array();

          const size_t size = certificatePolicy.X509CertificateProperties.Value()
                                  .SubjectAlternativeNames.Value()
                                  .DnsNames.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["x509_props"]["sans"]["dns_names"][i]
                = certificatePolicy.X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()[i];
          }
        }

        if (certificatePolicy.X509CertificateProperties.Value()
                .SubjectAlternativeNames.Value()
                .Upns.HasValue())
        {
          jsonRoot["x509_props"]["sans"]["upns"] = Core::Json::_internal::json::array();

          const size_t size = certificatePolicy.X509CertificateProperties.Value()
                                  .SubjectAlternativeNames.Value()
                                  .Upns.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["x509_props"]["sans"]["upns"][i]
                = certificatePolicy.X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()[i];
          }
        }
      }

      if (certificatePolicy.X509CertificateProperties.Value().KeyUsage.HasValue())
      {
        jsonRoot["x509_props"]["key_usage"] = Core::Json::_internal::json::array();

        const size_t size
            = certificatePolicy.X509CertificateProperties.Value().KeyUsage.Value().size();
        for (size_t i = 0; i < size; ++i)
        {
          jsonRoot["x509_props"]["key_usage"][i]
              = certificatePolicy.X509CertificateProperties.Value().KeyUsage.Value()[i].ToString();
        }
      }

      if (certificatePolicy.X509CertificateProperties.Value().ValidityInMonths.HasValue())
      {
        jsonRoot["x509_props"]["validity_months"]
            = certificatePolicy.X509CertificateProperties.Value().ValidityInMonths.Value();
      }
    }

    if (certificatePolicy.LifetimeActions.HasValue())
    {
      jsonRoot["lifetime_actions"] = Core::Json::_internal::json::array();

      const size_t size = certificatePolicy.LifetimeActions.Value().size();
      for (size_t i = 0; i < size; ++i)
      {
        if (certificatePolicy.LifetimeActions.Value()[i].Trigger.HasValue())
        {
          if (certificatePolicy.LifetimeActions.Value()[i]
                  .Trigger.Value()
                  .LifetimePercentage.HasValue())
          {
            jsonRoot["lifetime_actions"][i]["trigger"]["lifetime_percentage"]
                = certificatePolicy.LifetimeActions.Value()[i]
                      .Trigger.Value()
                      .LifetimePercentage.Value();
          }

          if (certificatePolicy.LifetimeActions.Value()[i]
                  .Trigger.Value()
                  .DaysBeforeExpiry.HasValue())
          {
            jsonRoot["lifetime_actions"][i]["trigger"]["days_before_expiry"]
                = certificatePolicy.LifetimeActions.Value()[i]
                      .Trigger.Value()
                      .DaysBeforeExpiry.Value();
          }
        }

        if (certificatePolicy.LifetimeActions.Value()[i].Action.HasValue())
        {
          if (certificatePolicy.LifetimeActions.Value()[i].Action.Value().ActionType.HasValue())
          {
            jsonRoot["lifetime_actions"][i]["action"]["action_type"]
                = certificatePolicy.LifetimeActions.Value()[i]
                      .Action.Value()
                      .ActionType.Value()
                      .ToString();
          }
        }
      }
    }

    if (certificatePolicy.IssuerParameters.HasValue())
    {
      if (certificatePolicy.IssuerParameters.Value().Name.HasValue())
      {
        jsonRoot["issuer"]["name"] = certificatePolicy.IssuerParameters.Value().Name.Value();
      }

      if (certificatePolicy.IssuerParameters.Value().CertificateType.HasValue())
      {
        jsonRoot["issuer"]["cty"]
            = certificatePolicy.IssuerParameters.Value().CertificateType.Value();
      }

      if (certificatePolicy.IssuerParameters.Value().CertificateTransparency.HasValue())
      {
        jsonRoot["issuer"]["cert_transparency"]
            = certificatePolicy.IssuerParameters.Value().CertificateTransparency.Value();
      }
    }

    if (certificatePolicy.Attributes.HasValue())
    {
      if (certificatePolicy.Attributes.Value().Enabled.HasValue())
      {
        jsonRoot["attributes"]["enabled"] = certificatePolicy.Attributes.Value().Enabled.Value();
      }

      if (certificatePolicy.Attributes.Value().NotBefore.HasValue())
      {
        jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            certificatePolicy.Attributes.Value().NotBefore.Value());
      }

      if (certificatePolicy.Attributes.Value().Expires.HasValue())
      {
        jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            certificatePolicy.Attributes.Value().Expires.Value());
      }

      if (certificatePolicy.Attributes.Value().Created.HasValue())
      {
        jsonRoot["attributes"]["created"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                certificatePolicy.Attributes.Value().Created.Value());
      }

      if (certificatePolicy.Attributes.Value().Updated.HasValue())
      {
        jsonRoot["attributes"]["updated"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                certificatePolicy.Attributes.Value().Updated.Value());
      }

      if (certificatePolicy.Attributes.Value().RecoverableDays.HasValue())
      {
        jsonRoot["attributes"]["recoverableDays"]
            = certificatePolicy.Attributes.Value().RecoverableDays.Value();
      }

      if (certificatePolicy.Attributes.Value().RecoveryLevel.HasValue())
      {
        jsonRoot["attributes"]["recoveryLevel"]
            = certificatePolicy.Attributes.Value().RecoveryLevel.Value().ToString();
      }
    }

    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Patch, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificatePolicy response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("key_props") && !jsonRoot["key_props"].is_null())
        {
          response.KeyProperties = Models::KeyProperties{};

          if (jsonRoot["key_props"].contains("exportable")
              && !jsonRoot["key_props"]["exportable"].is_null())
          {
            response.KeyProperties.Value().Exportable
                = jsonRoot["key_props"]["exportable"].get<bool>();
          }

          if (jsonRoot["key_props"].contains("kty") && !jsonRoot["key_props"]["kty"].is_null())
          {
            response.KeyProperties.Value().KeyType
                = Models::JsonWebKeyType(jsonRoot["key_props"]["kty"].get<std::string>());
          }

          if (jsonRoot["key_props"].contains("key_size")
              && !jsonRoot["key_props"]["key_size"].is_null())
          {
            response.KeyProperties.Value().KeySize = jsonRoot["key_props"]["key_size"].is_string()
                ? std::stoi(jsonRoot["key_props"]["key_size"].get<std::string>())
                : jsonRoot["key_props"]["key_size"].get<std::int32_t>();
          }

          if (jsonRoot["key_props"].contains("reuse_key")
              && !jsonRoot["key_props"]["reuse_key"].is_null())
          {
            response.KeyProperties.Value().ReuseKey
                = jsonRoot["key_props"]["reuse_key"].get<bool>();
          }

          if (jsonRoot["key_props"].contains("crv") && !jsonRoot["key_props"]["crv"].is_null())
          {
            response.KeyProperties.Value().Curve
                = Models::JsonWebKeyCurveName(jsonRoot["key_props"]["crv"].get<std::string>());
          }
        }

        if (jsonRoot.contains("secret_props") && !jsonRoot["secret_props"].is_null())
        {
          response.SecretProperties = Models::SecretProperties{};

          if (jsonRoot["secret_props"].contains("contentType")
              && !jsonRoot["secret_props"]["contentType"].is_null())
          {
            response.SecretProperties.Value().ContentType
                = jsonRoot["secret_props"]["contentType"].get<std::string>();
          }
        }

        if (jsonRoot.contains("x509_props") && !jsonRoot["x509_props"].is_null())
        {
          response.X509CertificateProperties = Models::X509CertificateProperties{};

          if (jsonRoot["x509_props"].contains("subject")
              && !jsonRoot["x509_props"]["subject"].is_null())
          {
            response.X509CertificateProperties.Value().Subject
                = jsonRoot["x509_props"]["subject"].get<std::string>();
          }

          if (jsonRoot["x509_props"].contains("ekus") && !jsonRoot["x509_props"]["ekus"].is_null())
          {
            response.X509CertificateProperties.Value().Ekus = std::vector<std::string>{};

            for (auto const& jsonItem : jsonRoot["x509_props"]["ekus"])
            {
              std::string vectorItem{};

              vectorItem = jsonItem.get<std::string>();

              response.X509CertificateProperties.Value().Ekus.Value().emplace_back(
                  std::move(vectorItem));
            }
          }

          if (jsonRoot["x509_props"].contains("sans") && !jsonRoot["x509_props"]["sans"].is_null())
          {
            response.X509CertificateProperties.Value().SubjectAlternativeNames
                = Models::SubjectAlternativeNames{};

            if (jsonRoot["x509_props"]["sans"].contains("emails")
                && !jsonRoot["x509_props"]["sans"]["emails"].is_null())
            {
              response.X509CertificateProperties.Value().SubjectAlternativeNames.Value().Emails
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["x509_props"]["sans"]["emails"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["x509_props"]["sans"].contains("dns_names")
                && !jsonRoot["x509_props"]["sans"]["dns_names"].is_null())
            {
              response.X509CertificateProperties.Value().SubjectAlternativeNames.Value().DnsNames
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["x509_props"]["sans"]["dns_names"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["x509_props"]["sans"].contains("upns")
                && !jsonRoot["x509_props"]["sans"]["upns"].is_null())
            {
              response.X509CertificateProperties.Value().SubjectAlternativeNames.Value().Upns
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["x509_props"]["sans"]["upns"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }
          }

          if (jsonRoot["x509_props"].contains("key_usage")
              && !jsonRoot["x509_props"]["key_usage"].is_null())
          {
            response.X509CertificateProperties.Value().KeyUsage
                = std::vector<Models::KeyUsageType>{};

            for (auto const& jsonItem : jsonRoot["x509_props"]["key_usage"])
            {
              Models::KeyUsageType vectorItem{};

              vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

              response.X509CertificateProperties.Value().KeyUsage.Value().emplace_back(
                  std::move(vectorItem));
            }
          }

          if (jsonRoot["x509_props"].contains("validity_months")
              && !jsonRoot["x509_props"]["validity_months"].is_null())
          {
            response.X509CertificateProperties.Value().ValidityInMonths
                = jsonRoot["x509_props"]["validity_months"].is_string()
                ? std::stoi(jsonRoot["x509_props"]["validity_months"].get<std::string>())
                : jsonRoot["x509_props"]["validity_months"].get<std::int32_t>();
          }
        }

        if (jsonRoot.contains("lifetime_actions") && !jsonRoot["lifetime_actions"].is_null())
        {
          response.LifetimeActions = std::vector<Models::LifetimeAction>{};

          for (auto const& jsonItem : jsonRoot["lifetime_actions"])
          {
            Models::LifetimeAction vectorItem{};

            if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
            {
              vectorItem.Trigger = Models::Trigger{};

              if (jsonItem["trigger"].contains("lifetime_percentage")
                  && !jsonItem["trigger"]["lifetime_percentage"].is_null())
              {
                vectorItem.Trigger.Value().LifetimePercentage
                    = jsonItem["trigger"]["lifetime_percentage"].is_string()
                    ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                    : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
              }

              if (jsonItem["trigger"].contains("days_before_expiry")
                  && !jsonItem["trigger"]["days_before_expiry"].is_null())
              {
                vectorItem.Trigger.Value().DaysBeforeExpiry
                    = jsonItem["trigger"]["days_before_expiry"].is_string()
                    ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                    : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
              }
            }

            if (jsonItem.contains("action") && !jsonItem["action"].is_null())
            {
              vectorItem.Action = Models::Action{};

              if (jsonItem["action"].contains("action_type")
                  && !jsonItem["action"]["action_type"].is_null())
              {
                vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                    jsonItem["action"]["action_type"].get<std::string>());
              }
            }

            response.LifetimeActions.Value().emplace_back(std::move(vectorItem));
          }
        }

        if (jsonRoot.contains("issuer") && !jsonRoot["issuer"].is_null())
        {
          response.IssuerParameters = Models::IssuerParameters{};

          if (jsonRoot["issuer"].contains("name") && !jsonRoot["issuer"]["name"].is_null())
          {
            response.IssuerParameters.Value().Name = jsonRoot["issuer"]["name"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cty") && !jsonRoot["issuer"]["cty"].is_null())
          {
            response.IssuerParameters.Value().CertificateType
                = jsonRoot["issuer"]["cty"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cert_transparency")
              && !jsonRoot["issuer"]["cert_transparency"].is_null())
          {
            response.IssuerParameters.Value().CertificateTransparency
                = jsonRoot["issuer"]["cert_transparency"].get<bool>();
          }
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificatePolicy>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateBundle>
KeyVaultClient::UpdateCertificate(
    const std::string& certificateName,
    const std::string& certificateVersion,
    const Models::CertificateUpdateParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  if (certificateVersion.empty())
  {
    throw std::invalid_argument("Parameter 'certificateVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateVersion));

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    if (parameters.CertificatePolicy.HasValue())
    {
      if (parameters.CertificatePolicy.Value().Id.HasValue())
      {
        jsonRoot["policy"]["id"] = parameters.CertificatePolicy.Value().Id.Value();
      }

      if (parameters.CertificatePolicy.Value().KeyProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value().KeyProperties.Value().Exportable.HasValue())
        {
          jsonRoot["policy"]["key_props"]["exportable"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().Exportable.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().KeyType.HasValue())
        {
          jsonRoot["policy"]["key_props"]["kty"] = parameters.CertificatePolicy.Value()
                                                       .KeyProperties.Value()
                                                       .KeyType.Value()
                                                       .ToString();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().KeySize.HasValue())
        {
          jsonRoot["policy"]["key_props"]["key_size"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().KeySize.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().ReuseKey.HasValue())
        {
          jsonRoot["policy"]["key_props"]["reuse_key"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().ReuseKey.Value();
        }

        if (parameters.CertificatePolicy.Value().KeyProperties.Value().Curve.HasValue())
        {
          jsonRoot["policy"]["key_props"]["crv"]
              = parameters.CertificatePolicy.Value().KeyProperties.Value().Curve.Value().ToString();
        }
      }

      if (parameters.CertificatePolicy.Value().SecretProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value().SecretProperties.Value().ContentType.HasValue())
        {
          jsonRoot["policy"]["secret_props"]["contentType"]
              = parameters.CertificatePolicy.Value().SecretProperties.Value().ContentType.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().X509CertificateProperties.HasValue())
      {
        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .Subject.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["subject"] = parameters.CertificatePolicy.Value()
                                                            .X509CertificateProperties.Value()
                                                            .Subject.Value();
        }

        if (parameters.CertificatePolicy.Value().X509CertificateProperties.Value().Ekus.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["ekus"] = Core::Json::_internal::json::array();

          const size_t size = parameters.CertificatePolicy.Value()
                                  .X509CertificateProperties.Value()
                                  .Ekus.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["policy"]["x509_props"]["ekus"][i] = parameters.CertificatePolicy.Value()
                                                              .X509CertificateProperties.Value()
                                                              .Ekus.Value()[i];
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .SubjectAlternativeNames.HasValue())
        {
          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .Emails.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["emails"]
                = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .Emails.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["emails"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .Emails.Value()[i];
            }
          }

          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .DnsNames.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["dns_names"]
                = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .DnsNames.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["dns_names"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .DnsNames.Value()[i];
            }
          }

          if (parameters.CertificatePolicy.Value()
                  .X509CertificateProperties.Value()
                  .SubjectAlternativeNames.Value()
                  .Upns.HasValue())
          {
            jsonRoot["policy"]["x509_props"]["sans"]["upns"] = Core::Json::_internal::json::array();

            const size_t size = parameters.CertificatePolicy.Value()
                                    .X509CertificateProperties.Value()
                                    .SubjectAlternativeNames.Value()
                                    .Upns.Value()
                                    .size();
            for (size_t i = 0; i < size; ++i)
            {
              jsonRoot["policy"]["x509_props"]["sans"]["upns"][i]
                  = parameters.CertificatePolicy.Value()
                        .X509CertificateProperties.Value()
                        .SubjectAlternativeNames.Value()
                        .Upns.Value()[i];
            }
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .KeyUsage.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["key_usage"] = Core::Json::_internal::json::array();

          const size_t size = parameters.CertificatePolicy.Value()
                                  .X509CertificateProperties.Value()
                                  .KeyUsage.Value()
                                  .size();
          for (size_t i = 0; i < size; ++i)
          {
            jsonRoot["policy"]["x509_props"]["key_usage"][i]
                = parameters.CertificatePolicy.Value()
                      .X509CertificateProperties.Value()
                      .KeyUsage.Value()[i]
                      .ToString();
          }
        }

        if (parameters.CertificatePolicy.Value()
                .X509CertificateProperties.Value()
                .ValidityInMonths.HasValue())
        {
          jsonRoot["policy"]["x509_props"]["validity_months"]
              = parameters.CertificatePolicy.Value()
                    .X509CertificateProperties.Value()
                    .ValidityInMonths.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().LifetimeActions.HasValue())
      {
        jsonRoot["policy"]["lifetime_actions"] = Core::Json::_internal::json::array();

        const size_t size = parameters.CertificatePolicy.Value().LifetimeActions.Value().size();
        for (size_t i = 0; i < size; ++i)
        {
          if (parameters.CertificatePolicy.Value().LifetimeActions.Value()[i].Trigger.HasValue())
          {
            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Trigger.Value()
                    .LifetimePercentage.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["trigger"]["lifetime_percentage"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Trigger.Value()
                        .LifetimePercentage.Value();
            }

            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Trigger.Value()
                    .DaysBeforeExpiry.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["trigger"]["days_before_expiry"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Trigger.Value()
                        .DaysBeforeExpiry.Value();
            }
          }

          if (parameters.CertificatePolicy.Value().LifetimeActions.Value()[i].Action.HasValue())
          {
            if (parameters.CertificatePolicy.Value()
                    .LifetimeActions.Value()[i]
                    .Action.Value()
                    .ActionType.HasValue())
            {
              jsonRoot["policy"]["lifetime_actions"][i]["action"]["action_type"]
                  = parameters.CertificatePolicy.Value()
                        .LifetimeActions.Value()[i]
                        .Action.Value()
                        .ActionType.Value()
                        .ToString();
            }
          }
        }
      }

      if (parameters.CertificatePolicy.Value().IssuerParameters.HasValue())
      {
        if (parameters.CertificatePolicy.Value().IssuerParameters.Value().Name.HasValue())
        {
          jsonRoot["policy"]["issuer"]["name"]
              = parameters.CertificatePolicy.Value().IssuerParameters.Value().Name.Value();
        }

        if (parameters.CertificatePolicy.Value()
                .IssuerParameters.Value()
                .CertificateType.HasValue())
        {
          jsonRoot["policy"]["issuer"]["cty"] = parameters.CertificatePolicy.Value()
                                                    .IssuerParameters.Value()
                                                    .CertificateType.Value();
        }

        if (parameters.CertificatePolicy.Value()
                .IssuerParameters.Value()
                .CertificateTransparency.HasValue())
        {
          jsonRoot["policy"]["issuer"]["cert_transparency"] = parameters.CertificatePolicy.Value()
                                                                  .IssuerParameters.Value()
                                                                  .CertificateTransparency.Value();
        }
      }

      if (parameters.CertificatePolicy.Value().Attributes.HasValue())
      {
        if (parameters.CertificatePolicy.Value().Attributes.Value().Enabled.HasValue())
        {
          jsonRoot["policy"]["attributes"]["enabled"]
              = parameters.CertificatePolicy.Value().Attributes.Value().Enabled.Value();
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().NotBefore.HasValue())
        {
          jsonRoot["policy"]["attributes"]["nbf"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().NotBefore.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Expires.HasValue())
        {
          jsonRoot["policy"]["attributes"]["exp"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Expires.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Created.HasValue())
        {
          jsonRoot["policy"]["attributes"]["created"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Created.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().Updated.HasValue())
        {
          jsonRoot["policy"]["attributes"]["updated"]
              = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                  parameters.CertificatePolicy.Value().Attributes.Value().Updated.Value());
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().RecoverableDays.HasValue())
        {
          jsonRoot["policy"]["attributes"]["recoverableDays"]
              = parameters.CertificatePolicy.Value().Attributes.Value().RecoverableDays.Value();
        }

        if (parameters.CertificatePolicy.Value().Attributes.Value().RecoveryLevel.HasValue())
        {
          jsonRoot["policy"]["attributes"]["recoveryLevel"] = parameters.CertificatePolicy.Value()
                                                                  .Attributes.Value()
                                                                  .RecoveryLevel.Value()
                                                                  .ToString();
        }
      }
    }

    if (parameters.CertificateAttributes.HasValue())
    {
      if (parameters.CertificateAttributes.Value().Enabled.HasValue())
      {
        jsonRoot["attributes"]["enabled"]
            = parameters.CertificateAttributes.Value().Enabled.Value();
      }

      if (parameters.CertificateAttributes.Value().NotBefore.HasValue())
      {
        jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            parameters.CertificateAttributes.Value().NotBefore.Value());
      }

      if (parameters.CertificateAttributes.Value().Expires.HasValue())
      {
        jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            parameters.CertificateAttributes.Value().Expires.Value());
      }

      if (parameters.CertificateAttributes.Value().Created.HasValue())
      {
        jsonRoot["attributes"]["created"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameters.CertificateAttributes.Value().Created.Value());
      }

      if (parameters.CertificateAttributes.Value().Updated.HasValue())
      {
        jsonRoot["attributes"]["updated"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameters.CertificateAttributes.Value().Updated.Value());
      }

      if (parameters.CertificateAttributes.Value().RecoverableDays.HasValue())
      {
        jsonRoot["attributes"]["recoverableDays"]
            = parameters.CertificateAttributes.Value().RecoverableDays.Value();
      }

      if (parameters.CertificateAttributes.Value().RecoveryLevel.HasValue())
      {
        jsonRoot["attributes"]["recoveryLevel"]
            = parameters.CertificateAttributes.Value().RecoveryLevel.Value().ToString();
      }
    }

    if (parameters.Tags.HasValue())
    {
      jsonRoot["tags"] = Core::Json::_internal::json::object();

      for (auto const& kv : parameters.Tags.Value())
      {
        jsonRoot["tags"][kv.first] = kv.second;
      }
    }

    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Patch, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

        if (jsonRoot.contains("sid") && !jsonRoot["sid"].is_null())
        {
          response.Sid = jsonRoot["sid"].get<std::string>();
        }

        if (jsonRoot.contains("x5t") && !jsonRoot["x5t"].is_null())
        {
          response.X509Thumbprint
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["x5t"].get<std::string>());
        }

        if (jsonRoot.contains("policy") && !jsonRoot["policy"].is_null())
        {
          response.Policy = Models::CertificatePolicy{};

          if (jsonRoot["policy"].contains("id") && !jsonRoot["policy"]["id"].is_null())
          {
            response.Policy.Value().Id = jsonRoot["policy"]["id"].get<std::string>();
          }

          if (jsonRoot["policy"].contains("key_props")
              && !jsonRoot["policy"]["key_props"].is_null())
          {
            response.Policy.Value().KeyProperties = Models::KeyProperties{};

            if (jsonRoot["policy"]["key_props"].contains("exportable")
                && !jsonRoot["policy"]["key_props"]["exportable"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Exportable
                  = jsonRoot["policy"]["key_props"]["exportable"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("kty")
                && !jsonRoot["policy"]["key_props"]["kty"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeyType = Models::JsonWebKeyType(
                  jsonRoot["policy"]["key_props"]["kty"].get<std::string>());
            }

            if (jsonRoot["policy"]["key_props"].contains("key_size")
                && !jsonRoot["policy"]["key_props"]["key_size"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeySize
                  = jsonRoot["policy"]["key_props"]["key_size"].is_string()
                  ? std::stoi(jsonRoot["policy"]["key_props"]["key_size"].get<std::string>())
                  : jsonRoot["policy"]["key_props"]["key_size"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["key_props"].contains("reuse_key")
                && !jsonRoot["policy"]["key_props"]["reuse_key"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().ReuseKey
                  = jsonRoot["policy"]["key_props"]["reuse_key"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("crv")
                && !jsonRoot["policy"]["key_props"]["crv"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Curve = Models::JsonWebKeyCurveName(
                  jsonRoot["policy"]["key_props"]["crv"].get<std::string>());
            }
          }

          if (jsonRoot["policy"].contains("secret_props")
              && !jsonRoot["policy"]["secret_props"].is_null())
          {
            response.Policy.Value().SecretProperties = Models::SecretProperties{};

            if (jsonRoot["policy"]["secret_props"].contains("contentType")
                && !jsonRoot["policy"]["secret_props"]["contentType"].is_null())
            {
              response.Policy.Value().SecretProperties.Value().ContentType
                  = jsonRoot["policy"]["secret_props"]["contentType"].get<std::string>();
            }
          }

          if (jsonRoot["policy"].contains("x509_props")
              && !jsonRoot["policy"]["x509_props"].is_null())
          {
            response.Policy.Value().X509CertificateProperties = Models::X509CertificateProperties{};

            if (jsonRoot["policy"]["x509_props"].contains("subject")
                && !jsonRoot["policy"]["x509_props"]["subject"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Subject
                  = jsonRoot["policy"]["x509_props"]["subject"].get<std::string>();
            }

            if (jsonRoot["policy"]["x509_props"].contains("ekus")
                && !jsonRoot["policy"]["x509_props"]["ekus"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Ekus
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["ekus"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.Policy.Value().X509CertificateProperties.Value().Ekus.Value().emplace_back(
                    std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("sans")
                && !jsonRoot["policy"]["x509_props"]["sans"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().SubjectAlternativeNames
                  = Models::SubjectAlternativeNames{};

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("emails")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["emails"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["emails"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("dns_names")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["dns_names"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["dns_names"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("upns")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["upns"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["upns"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("key_usage")
                && !jsonRoot["policy"]["x509_props"]["key_usage"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().KeyUsage
                  = std::vector<Models::KeyUsageType>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["key_usage"])
              {
                Models::KeyUsageType vectorItem{};

                vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .KeyUsage.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("validity_months")
                && !jsonRoot["policy"]["x509_props"]["validity_months"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().ValidityInMonths
                  = jsonRoot["policy"]["x509_props"]["validity_months"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["x509_props"]["validity_months"].get<std::string>())
                  : jsonRoot["policy"]["x509_props"]["validity_months"].get<std::int32_t>();
            }
          }

          if (jsonRoot["policy"].contains("lifetime_actions")
              && !jsonRoot["policy"]["lifetime_actions"].is_null())
          {
            response.Policy.Value().LifetimeActions = std::vector<Models::LifetimeAction>{};

            for (auto const& jsonItem : jsonRoot["policy"]["lifetime_actions"])
            {
              Models::LifetimeAction vectorItem{};

              if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
              {
                vectorItem.Trigger = Models::Trigger{};

                if (jsonItem["trigger"].contains("lifetime_percentage")
                    && !jsonItem["trigger"]["lifetime_percentage"].is_null())
                {
                  vectorItem.Trigger.Value().LifetimePercentage
                      = jsonItem["trigger"]["lifetime_percentage"].is_string()
                      ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                      : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
                }

                if (jsonItem["trigger"].contains("days_before_expiry")
                    && !jsonItem["trigger"]["days_before_expiry"].is_null())
                {
                  vectorItem.Trigger.Value().DaysBeforeExpiry
                      = jsonItem["trigger"]["days_before_expiry"].is_string()
                      ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                      : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
                }
              }

              if (jsonItem.contains("action") && !jsonItem["action"].is_null())
              {
                vectorItem.Action = Models::Action{};

                if (jsonItem["action"].contains("action_type")
                    && !jsonItem["action"]["action_type"].is_null())
                {
                  vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                      jsonItem["action"]["action_type"].get<std::string>());
                }
              }

              response.Policy.Value().LifetimeActions.Value().emplace_back(std::move(vectorItem));
            }
          }

          if (jsonRoot["policy"].contains("issuer") && !jsonRoot["policy"]["issuer"].is_null())
          {
            response.Policy.Value().IssuerParameters = Models::IssuerParameters{};

            if (jsonRoot["policy"]["issuer"].contains("name")
                && !jsonRoot["policy"]["issuer"]["name"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().Name
                  = jsonRoot["policy"]["issuer"]["name"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cty")
                && !jsonRoot["policy"]["issuer"]["cty"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateType
                  = jsonRoot["policy"]["issuer"]["cty"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cert_transparency")
                && !jsonRoot["policy"]["issuer"]["cert_transparency"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateTransparency
                  = jsonRoot["policy"]["issuer"]["cert_transparency"].get<bool>();
            }
          }

          if (jsonRoot["policy"].contains("attributes")
              && !jsonRoot["policy"]["attributes"].is_null())
          {
            response.Policy.Value().Attributes = Models::CertificateAttributes{};

            if (jsonRoot["policy"]["attributes"].contains("enabled")
                && !jsonRoot["policy"]["attributes"]["enabled"].is_null())
            {
              response.Policy.Value().Attributes.Value().Enabled
                  = jsonRoot["policy"]["attributes"]["enabled"].get<bool>();
            }

            if (jsonRoot["policy"]["attributes"].contains("nbf")
                && !jsonRoot["policy"]["attributes"]["nbf"].is_null())
            {
              response.Policy.Value().Attributes.Value().NotBefore
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["nbf"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["nbf"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["nbf"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("exp")
                && !jsonRoot["policy"]["attributes"]["exp"].is_null())
            {
              response.Policy.Value().Attributes.Value().Expires
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["exp"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["exp"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["exp"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("created")
                && !jsonRoot["policy"]["attributes"]["created"].is_null())
            {
              response.Policy.Value().Attributes.Value().Created
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["created"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["created"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["created"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("updated")
                && !jsonRoot["policy"]["attributes"]["updated"].is_null())
            {
              response.Policy.Value().Attributes.Value().Updated
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["updated"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["updated"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["updated"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("recoverableDays")
                && !jsonRoot["policy"]["attributes"]["recoverableDays"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoverableDays
                  = jsonRoot["policy"]["attributes"]["recoverableDays"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::string>())
                  : jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["attributes"].contains("recoveryLevel")
                && !jsonRoot["policy"]["attributes"]["recoveryLevel"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoveryLevel
                  = Models::DeletionRecoveryLevel(
                      jsonRoot["policy"]["attributes"]["recoveryLevel"].get<std::string>());
            }
          }
        }

        if (jsonRoot.contains("cer") && !jsonRoot["cer"].is_null())
        {
          response.Cer = Core::Convert::Base64Decode(jsonRoot["cer"].get<std::string>());
        }

        if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null())
        {
          response.ContentType = jsonRoot["contentType"].get<std::string>();
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }

        if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null())
        {
          response.Tags = std::map<std::string, std::string>{};

          for (auto const& kv : jsonRoot["tags"].items())
          {
            std::string value{};
            value = kv.value().get<std::string>();
            response.Tags.Value().emplace(kv.key(), value);
          }
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateBundle>(std::move(response), std::move(rawResponse));
}

// codegen: replace KeyVaultClient::GetCertificate
Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateBundle>
KeyVaultClient::GetCertificate(
    const std::string& certificateName,
    const std::string& certificateVersion,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  if (!certificateVersion.empty())
  {
    url.AppendPath(Core::Url::Encode(certificateVersion));
  }

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

        if (jsonRoot.contains("sid") && !jsonRoot["sid"].is_null())
        {
          response.Sid = jsonRoot["sid"].get<std::string>();
        }

        if (jsonRoot.contains("x5t") && !jsonRoot["x5t"].is_null())
        {
          response.X509Thumbprint
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["x5t"].get<std::string>());
        }

        if (jsonRoot.contains("policy") && !jsonRoot["policy"].is_null())
        {
          response.Policy = Models::CertificatePolicy{};

          if (jsonRoot["policy"].contains("id") && !jsonRoot["policy"]["id"].is_null())
          {
            response.Policy.Value().Id = jsonRoot["policy"]["id"].get<std::string>();
          }

          if (jsonRoot["policy"].contains("key_props")
              && !jsonRoot["policy"]["key_props"].is_null())
          {
            response.Policy.Value().KeyProperties = Models::KeyProperties{};

            if (jsonRoot["policy"]["key_props"].contains("exportable")
                && !jsonRoot["policy"]["key_props"]["exportable"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Exportable
                  = jsonRoot["policy"]["key_props"]["exportable"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("kty")
                && !jsonRoot["policy"]["key_props"]["kty"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeyType = Models::JsonWebKeyType(
                  jsonRoot["policy"]["key_props"]["kty"].get<std::string>());
            }

            if (jsonRoot["policy"]["key_props"].contains("key_size")
                && !jsonRoot["policy"]["key_props"]["key_size"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeySize
                  = jsonRoot["policy"]["key_props"]["key_size"].is_string()
                  ? std::stoi(jsonRoot["policy"]["key_props"]["key_size"].get<std::string>())
                  : jsonRoot["policy"]["key_props"]["key_size"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["key_props"].contains("reuse_key")
                && !jsonRoot["policy"]["key_props"]["reuse_key"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().ReuseKey
                  = jsonRoot["policy"]["key_props"]["reuse_key"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("crv")
                && !jsonRoot["policy"]["key_props"]["crv"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Curve = Models::JsonWebKeyCurveName(
                  jsonRoot["policy"]["key_props"]["crv"].get<std::string>());
            }
          }

          if (jsonRoot["policy"].contains("secret_props")
              && !jsonRoot["policy"]["secret_props"].is_null())
          {
            response.Policy.Value().SecretProperties = Models::SecretProperties{};

            if (jsonRoot["policy"]["secret_props"].contains("contentType")
                && !jsonRoot["policy"]["secret_props"]["contentType"].is_null())
            {
              response.Policy.Value().SecretProperties.Value().ContentType
                  = jsonRoot["policy"]["secret_props"]["contentType"].get<std::string>();
            }
          }

          if (jsonRoot["policy"].contains("x509_props")
              && !jsonRoot["policy"]["x509_props"].is_null())
          {
            response.Policy.Value().X509CertificateProperties = Models::X509CertificateProperties{};

            if (jsonRoot["policy"]["x509_props"].contains("subject")
                && !jsonRoot["policy"]["x509_props"]["subject"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Subject
                  = jsonRoot["policy"]["x509_props"]["subject"].get<std::string>();
            }

            if (jsonRoot["policy"]["x509_props"].contains("ekus")
                && !jsonRoot["policy"]["x509_props"]["ekus"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Ekus
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["ekus"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.Policy.Value().X509CertificateProperties.Value().Ekus.Value().emplace_back(
                    std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("sans")
                && !jsonRoot["policy"]["x509_props"]["sans"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().SubjectAlternativeNames
                  = Models::SubjectAlternativeNames{};

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("emails")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["emails"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["emails"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("dns_names")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["dns_names"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["dns_names"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("upns")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["upns"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["upns"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("key_usage")
                && !jsonRoot["policy"]["x509_props"]["key_usage"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().KeyUsage
                  = std::vector<Models::KeyUsageType>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["key_usage"])
              {
                Models::KeyUsageType vectorItem{};

                vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .KeyUsage.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("validity_months")
                && !jsonRoot["policy"]["x509_props"]["validity_months"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().ValidityInMonths
                  = jsonRoot["policy"]["x509_props"]["validity_months"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["x509_props"]["validity_months"].get<std::string>())
                  : jsonRoot["policy"]["x509_props"]["validity_months"].get<std::int32_t>();
            }
          }

          if (jsonRoot["policy"].contains("lifetime_actions")
              && !jsonRoot["policy"]["lifetime_actions"].is_null())
          {
            response.Policy.Value().LifetimeActions = std::vector<Models::LifetimeAction>{};

            for (auto const& jsonItem : jsonRoot["policy"]["lifetime_actions"])
            {
              Models::LifetimeAction vectorItem{};

              if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
              {
                vectorItem.Trigger = Models::Trigger{};

                if (jsonItem["trigger"].contains("lifetime_percentage")
                    && !jsonItem["trigger"]["lifetime_percentage"].is_null())
                {
                  vectorItem.Trigger.Value().LifetimePercentage
                      = jsonItem["trigger"]["lifetime_percentage"].is_string()
                      ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                      : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
                }

                if (jsonItem["trigger"].contains("days_before_expiry")
                    && !jsonItem["trigger"]["days_before_expiry"].is_null())
                {
                  vectorItem.Trigger.Value().DaysBeforeExpiry
                      = jsonItem["trigger"]["days_before_expiry"].is_string()
                      ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                      : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
                }
              }

              if (jsonItem.contains("action") && !jsonItem["action"].is_null())
              {
                vectorItem.Action = Models::Action{};

                if (jsonItem["action"].contains("action_type")
                    && !jsonItem["action"]["action_type"].is_null())
                {
                  vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                      jsonItem["action"]["action_type"].get<std::string>());
                }
              }

              response.Policy.Value().LifetimeActions.Value().emplace_back(std::move(vectorItem));
            }
          }

          if (jsonRoot["policy"].contains("issuer") && !jsonRoot["policy"]["issuer"].is_null())
          {
            response.Policy.Value().IssuerParameters = Models::IssuerParameters{};

            if (jsonRoot["policy"]["issuer"].contains("name")
                && !jsonRoot["policy"]["issuer"]["name"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().Name
                  = jsonRoot["policy"]["issuer"]["name"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cty")
                && !jsonRoot["policy"]["issuer"]["cty"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateType
                  = jsonRoot["policy"]["issuer"]["cty"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cert_transparency")
                && !jsonRoot["policy"]["issuer"]["cert_transparency"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateTransparency
                  = jsonRoot["policy"]["issuer"]["cert_transparency"].get<bool>();
            }
          }

          if (jsonRoot["policy"].contains("attributes")
              && !jsonRoot["policy"]["attributes"].is_null())
          {
            response.Policy.Value().Attributes = Models::CertificateAttributes{};

            if (jsonRoot["policy"]["attributes"].contains("enabled")
                && !jsonRoot["policy"]["attributes"]["enabled"].is_null())
            {
              response.Policy.Value().Attributes.Value().Enabled
                  = jsonRoot["policy"]["attributes"]["enabled"].get<bool>();
            }

            if (jsonRoot["policy"]["attributes"].contains("nbf")
                && !jsonRoot["policy"]["attributes"]["nbf"].is_null())
            {
              response.Policy.Value().Attributes.Value().NotBefore
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["nbf"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["nbf"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["nbf"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("exp")
                && !jsonRoot["policy"]["attributes"]["exp"].is_null())
            {
              response.Policy.Value().Attributes.Value().Expires
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["exp"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["exp"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["exp"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("created")
                && !jsonRoot["policy"]["attributes"]["created"].is_null())
            {
              response.Policy.Value().Attributes.Value().Created
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["created"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["created"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["created"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("updated")
                && !jsonRoot["policy"]["attributes"]["updated"].is_null())
            {
              response.Policy.Value().Attributes.Value().Updated
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["updated"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["updated"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["updated"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("recoverableDays")
                && !jsonRoot["policy"]["attributes"]["recoverableDays"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoverableDays
                  = jsonRoot["policy"]["attributes"]["recoverableDays"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::string>())
                  : jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["attributes"].contains("recoveryLevel")
                && !jsonRoot["policy"]["attributes"]["recoveryLevel"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoveryLevel
                  = Models::DeletionRecoveryLevel(
                      jsonRoot["policy"]["attributes"]["recoveryLevel"].get<std::string>());
            }
          }
        }

        if (jsonRoot.contains("cer") && !jsonRoot["cer"].is_null())
        {
          response.Cer = Core::Convert::Base64Decode(jsonRoot["cer"].get<std::string>());
        }

        if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null())
        {
          response.ContentType = jsonRoot["contentType"].get<std::string>();
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }

        if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null())
        {
          response.Tags = std::map<std::string, std::string>{};

          for (auto const& kv : jsonRoot["tags"].items())
          {
            std::string value{};
            value = kv.value().get<std::string>();
            response.Tags.Value().emplace(kv.key(), value);
          }
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateBundle>(std::move(response), std::move(rawResponse));
}

// codegen: end replace KeyVaultClient::GetCertificate
Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateOperation>
KeyVaultClient::UpdateCertificateOperation(
    const std::string& certificateName,
    const Models::CertificateOperationUpdateParameter& certificateOperation,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("pending");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["cancellation_requested"] = certificateOperation.CancellationRequested;
    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Patch, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateOperation response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("issuer") && !jsonRoot["issuer"].is_null())
        {
          response.IssuerParameters = Models::IssuerParameters{};

          if (jsonRoot["issuer"].contains("name") && !jsonRoot["issuer"]["name"].is_null())
          {
            response.IssuerParameters.Value().Name = jsonRoot["issuer"]["name"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cty") && !jsonRoot["issuer"]["cty"].is_null())
          {
            response.IssuerParameters.Value().CertificateType
                = jsonRoot["issuer"]["cty"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cert_transparency")
              && !jsonRoot["issuer"]["cert_transparency"].is_null())
          {
            response.IssuerParameters.Value().CertificateTransparency
                = jsonRoot["issuer"]["cert_transparency"].get<bool>();
          }
        }

        if (jsonRoot.contains("csr") && !jsonRoot["csr"].is_null())
        {
          response.Csr = Core::Convert::Base64Decode(jsonRoot["csr"].get<std::string>());
        }

        if (jsonRoot.contains("cancellation_requested")
            && !jsonRoot["cancellation_requested"].is_null())
        {
          response.CancellationRequested = jsonRoot["cancellation_requested"].get<bool>();
        }

        if (jsonRoot.contains("status") && !jsonRoot["status"].is_null())
        {
          response.Status = jsonRoot["status"].get<std::string>();
        }

        if (jsonRoot.contains("status_details") && !jsonRoot["status_details"].is_null())
        {
          response.StatusDetails = jsonRoot["status_details"].get<std::string>();
        }

        const std::function<void(Models::KeyVaultErrorError&, Core::Json::_internal::json const&)>
            deserializeKeyVaultErrorError = [&](Models::KeyVaultErrorError& keyVaultErrorError,
                                                Core::Json::_internal::json const& jsonItem) {
              if (jsonItem.contains("code") && !jsonItem["code"].is_null())
              {
                keyVaultErrorError.Code = jsonItem["code"].get<std::string>();
              }

              if (jsonItem.contains("message") && !jsonItem["message"].is_null())
              {
                keyVaultErrorError.Message = jsonItem["message"].get<std::string>();
              }

              const std::function<void(
                  std::shared_ptr<Models::KeyVaultErrorError>&, Core::Json::_internal::json const&)>
                  deserializeKeyVaultErrorErrorPtr
                  = [&](std::shared_ptr<Models::KeyVaultErrorError>& keyVaultErrorError,
                        Core::Json::_internal::json const& jsonItem) {
                      if (jsonItem.contains("code") && !jsonItem["code"].is_null())
                      {
                        if (!keyVaultErrorError)
                        {
                          keyVaultErrorError = std::make_shared<Models::KeyVaultErrorError>();
                        }

                        keyVaultErrorError->Code = jsonItem["code"].get<std::string>();
                      }

                      if (jsonItem.contains("message") && !jsonItem["message"].is_null())
                      {
                        if (!keyVaultErrorError)
                        {
                          keyVaultErrorError = std::make_shared<Models::KeyVaultErrorError>();
                        }

                        keyVaultErrorError->Message = jsonItem["message"].get<std::string>();
                      }

                      deserializeKeyVaultErrorErrorPtr(
                          keyVaultErrorError->InnerError, jsonItem["innererror"]);
                    };
              deserializeKeyVaultErrorErrorPtr(
                  keyVaultErrorError.InnerError, jsonItem["innererror"]);
            };
        if (jsonRoot.contains("error") && !jsonRoot["error"].is_null())
        {
          response.Error = Models::KeyVaultErrorError{};
          deserializeKeyVaultErrorError(response.Error.Value(), jsonRoot["error"]);
        }

        if (jsonRoot.contains("target") && !jsonRoot["target"].is_null())
        {
          response.Target = jsonRoot["target"].get<std::string>();
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }

        if (jsonRoot.contains("request_id") && !jsonRoot["request_id"].is_null())
        {
          response.RequestId = jsonRoot["request_id"].get<std::string>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateOperation>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateOperation>
KeyVaultClient::GetCertificateOperation(
    const std::string& certificateName,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("pending");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateOperation response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("issuer") && !jsonRoot["issuer"].is_null())
        {
          response.IssuerParameters = Models::IssuerParameters{};

          if (jsonRoot["issuer"].contains("name") && !jsonRoot["issuer"]["name"].is_null())
          {
            response.IssuerParameters.Value().Name = jsonRoot["issuer"]["name"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cty") && !jsonRoot["issuer"]["cty"].is_null())
          {
            response.IssuerParameters.Value().CertificateType
                = jsonRoot["issuer"]["cty"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cert_transparency")
              && !jsonRoot["issuer"]["cert_transparency"].is_null())
          {
            response.IssuerParameters.Value().CertificateTransparency
                = jsonRoot["issuer"]["cert_transparency"].get<bool>();
          }
        }

        if (jsonRoot.contains("csr") && !jsonRoot["csr"].is_null())
        {
          response.Csr = Core::Convert::Base64Decode(jsonRoot["csr"].get<std::string>());
        }

        if (jsonRoot.contains("cancellation_requested")
            && !jsonRoot["cancellation_requested"].is_null())
        {
          response.CancellationRequested = jsonRoot["cancellation_requested"].get<bool>();
        }

        if (jsonRoot.contains("status") && !jsonRoot["status"].is_null())
        {
          response.Status = jsonRoot["status"].get<std::string>();
        }

        if (jsonRoot.contains("status_details") && !jsonRoot["status_details"].is_null())
        {
          response.StatusDetails = jsonRoot["status_details"].get<std::string>();
        }

        const std::function<void(Models::KeyVaultErrorError&, Core::Json::_internal::json const&)>
            deserializeKeyVaultErrorError = [&](Models::KeyVaultErrorError& keyVaultErrorError,
                                                Core::Json::_internal::json const& jsonItem) {
              if (jsonItem.contains("code") && !jsonItem["code"].is_null())
              {
                keyVaultErrorError.Code = jsonItem["code"].get<std::string>();
              }

              if (jsonItem.contains("message") && !jsonItem["message"].is_null())
              {
                keyVaultErrorError.Message = jsonItem["message"].get<std::string>();
              }

              const std::function<void(
                  std::shared_ptr<Models::KeyVaultErrorError>&, Core::Json::_internal::json const&)>
                  deserializeKeyVaultErrorErrorPtr
                  = [&](std::shared_ptr<Models::KeyVaultErrorError>& keyVaultErrorError,
                        Core::Json::_internal::json const& jsonItem) {
                      if (jsonItem.contains("code") && !jsonItem["code"].is_null())
                      {
                        if (!keyVaultErrorError)
                        {
                          keyVaultErrorError = std::make_shared<Models::KeyVaultErrorError>();
                        }

                        keyVaultErrorError->Code = jsonItem["code"].get<std::string>();
                      }

                      if (jsonItem.contains("message") && !jsonItem["message"].is_null())
                      {
                        if (!keyVaultErrorError)
                        {
                          keyVaultErrorError = std::make_shared<Models::KeyVaultErrorError>();
                        }

                        keyVaultErrorError->Message = jsonItem["message"].get<std::string>();
                      }

                      deserializeKeyVaultErrorErrorPtr(
                          keyVaultErrorError->InnerError, jsonItem["innererror"]);
                    };
              deserializeKeyVaultErrorErrorPtr(
                  keyVaultErrorError.InnerError, jsonItem["innererror"]);
            };
        if (jsonRoot.contains("error") && !jsonRoot["error"].is_null())
        {
          response.Error = Models::KeyVaultErrorError{};
          deserializeKeyVaultErrorError(response.Error.Value(), jsonRoot["error"]);
        }

        if (jsonRoot.contains("target") && !jsonRoot["target"].is_null())
        {
          response.Target = jsonRoot["target"].get<std::string>();
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }

        if (jsonRoot.contains("request_id") && !jsonRoot["request_id"].is_null())
        {
          response.RequestId = jsonRoot["request_id"].get<std::string>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateOperation>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateOperation>
KeyVaultClient::DeleteCertificateOperation(
    const std::string& certificateName,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("pending");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Delete, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateOperation response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("issuer") && !jsonRoot["issuer"].is_null())
        {
          response.IssuerParameters = Models::IssuerParameters{};

          if (jsonRoot["issuer"].contains("name") && !jsonRoot["issuer"]["name"].is_null())
          {
            response.IssuerParameters.Value().Name = jsonRoot["issuer"]["name"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cty") && !jsonRoot["issuer"]["cty"].is_null())
          {
            response.IssuerParameters.Value().CertificateType
                = jsonRoot["issuer"]["cty"].get<std::string>();
          }

          if (jsonRoot["issuer"].contains("cert_transparency")
              && !jsonRoot["issuer"]["cert_transparency"].is_null())
          {
            response.IssuerParameters.Value().CertificateTransparency
                = jsonRoot["issuer"]["cert_transparency"].get<bool>();
          }
        }

        if (jsonRoot.contains("csr") && !jsonRoot["csr"].is_null())
        {
          response.Csr = Core::Convert::Base64Decode(jsonRoot["csr"].get<std::string>());
        }

        if (jsonRoot.contains("cancellation_requested")
            && !jsonRoot["cancellation_requested"].is_null())
        {
          response.CancellationRequested = jsonRoot["cancellation_requested"].get<bool>();
        }

        if (jsonRoot.contains("status") && !jsonRoot["status"].is_null())
        {
          response.Status = jsonRoot["status"].get<std::string>();
        }

        if (jsonRoot.contains("status_details") && !jsonRoot["status_details"].is_null())
        {
          response.StatusDetails = jsonRoot["status_details"].get<std::string>();
        }

        const std::function<void(Models::KeyVaultErrorError&, Core::Json::_internal::json const&)>
            deserializeKeyVaultErrorError = [&](Models::KeyVaultErrorError& keyVaultErrorError,
                                                Core::Json::_internal::json const& jsonItem) {
              if (jsonItem.contains("code") && !jsonItem["code"].is_null())
              {
                keyVaultErrorError.Code = jsonItem["code"].get<std::string>();
              }

              if (jsonItem.contains("message") && !jsonItem["message"].is_null())
              {
                keyVaultErrorError.Message = jsonItem["message"].get<std::string>();
              }

              const std::function<void(
                  std::shared_ptr<Models::KeyVaultErrorError>&, Core::Json::_internal::json const&)>
                  deserializeKeyVaultErrorErrorPtr
                  = [&](std::shared_ptr<Models::KeyVaultErrorError>& keyVaultErrorError,
                        Core::Json::_internal::json const& jsonItem) {
                      if (jsonItem.contains("code") && !jsonItem["code"].is_null())
                      {
                        if (!keyVaultErrorError)
                        {
                          keyVaultErrorError = std::make_shared<Models::KeyVaultErrorError>();
                        }

                        keyVaultErrorError->Code = jsonItem["code"].get<std::string>();
                      }

                      if (jsonItem.contains("message") && !jsonItem["message"].is_null())
                      {
                        if (!keyVaultErrorError)
                        {
                          keyVaultErrorError = std::make_shared<Models::KeyVaultErrorError>();
                        }

                        keyVaultErrorError->Message = jsonItem["message"].get<std::string>();
                      }

                      deserializeKeyVaultErrorErrorPtr(
                          keyVaultErrorError->InnerError, jsonItem["innererror"]);
                    };
              deserializeKeyVaultErrorErrorPtr(
                  keyVaultErrorError.InnerError, jsonItem["innererror"]);
            };
        if (jsonRoot.contains("error") && !jsonRoot["error"].is_null())
        {
          response.Error = Models::KeyVaultErrorError{};
          deserializeKeyVaultErrorError(response.Error.Value(), jsonRoot["error"]);
        }

        if (jsonRoot.contains("target") && !jsonRoot["target"].is_null())
        {
          response.Target = jsonRoot["target"].get<std::string>();
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }

        if (jsonRoot.contains("request_id") && !jsonRoot["request_id"].is_null())
        {
          response.RequestId = jsonRoot["request_id"].get<std::string>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateOperation>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateBundle>
KeyVaultClient::MergeCertificate(
    const std::string& certificateName,
    const Models::CertificateMergeParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("pending/merge");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    const size_t size = parameters.X509Certificates.size();
    for (size_t i = 0; i < size; ++i)
    {
      jsonRoot["x5c"][i] = Core::Convert::Base64Encode(parameters.X509Certificates[i]);
    }

    if (parameters.CertificateAttributes.HasValue())
    {
      if (parameters.CertificateAttributes.Value().Enabled.HasValue())
      {
        jsonRoot["attributes"]["enabled"]
            = parameters.CertificateAttributes.Value().Enabled.Value();
      }

      if (parameters.CertificateAttributes.Value().NotBefore.HasValue())
      {
        jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            parameters.CertificateAttributes.Value().NotBefore.Value());
      }

      if (parameters.CertificateAttributes.Value().Expires.HasValue())
      {
        jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
            parameters.CertificateAttributes.Value().Expires.Value());
      }

      if (parameters.CertificateAttributes.Value().Created.HasValue())
      {
        jsonRoot["attributes"]["created"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameters.CertificateAttributes.Value().Created.Value());
      }

      if (parameters.CertificateAttributes.Value().Updated.HasValue())
      {
        jsonRoot["attributes"]["updated"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                parameters.CertificateAttributes.Value().Updated.Value());
      }

      if (parameters.CertificateAttributes.Value().RecoverableDays.HasValue())
      {
        jsonRoot["attributes"]["recoverableDays"]
            = parameters.CertificateAttributes.Value().RecoverableDays.Value();
      }

      if (parameters.CertificateAttributes.Value().RecoveryLevel.HasValue())
      {
        jsonRoot["attributes"]["recoveryLevel"]
            = parameters.CertificateAttributes.Value().RecoveryLevel.Value().ToString();
      }
    }

    if (parameters.Tags.HasValue())
    {
      jsonRoot["tags"] = Core::Json::_internal::json::object();

      for (auto const& kv : parameters.Tags.Value())
      {
        jsonRoot["tags"][kv.first] = kv.second;
      }
    }

    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Created)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

        if (jsonRoot.contains("sid") && !jsonRoot["sid"].is_null())
        {
          response.Sid = jsonRoot["sid"].get<std::string>();
        }

        if (jsonRoot.contains("x5t") && !jsonRoot["x5t"].is_null())
        {
          response.X509Thumbprint
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["x5t"].get<std::string>());
        }

        if (jsonRoot.contains("policy") && !jsonRoot["policy"].is_null())
        {
          response.Policy = Models::CertificatePolicy{};

          if (jsonRoot["policy"].contains("id") && !jsonRoot["policy"]["id"].is_null())
          {
            response.Policy.Value().Id = jsonRoot["policy"]["id"].get<std::string>();
          }

          if (jsonRoot["policy"].contains("key_props")
              && !jsonRoot["policy"]["key_props"].is_null())
          {
            response.Policy.Value().KeyProperties = Models::KeyProperties{};

            if (jsonRoot["policy"]["key_props"].contains("exportable")
                && !jsonRoot["policy"]["key_props"]["exportable"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Exportable
                  = jsonRoot["policy"]["key_props"]["exportable"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("kty")
                && !jsonRoot["policy"]["key_props"]["kty"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeyType = Models::JsonWebKeyType(
                  jsonRoot["policy"]["key_props"]["kty"].get<std::string>());
            }

            if (jsonRoot["policy"]["key_props"].contains("key_size")
                && !jsonRoot["policy"]["key_props"]["key_size"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeySize
                  = jsonRoot["policy"]["key_props"]["key_size"].is_string()
                  ? std::stoi(jsonRoot["policy"]["key_props"]["key_size"].get<std::string>())
                  : jsonRoot["policy"]["key_props"]["key_size"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["key_props"].contains("reuse_key")
                && !jsonRoot["policy"]["key_props"]["reuse_key"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().ReuseKey
                  = jsonRoot["policy"]["key_props"]["reuse_key"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("crv")
                && !jsonRoot["policy"]["key_props"]["crv"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Curve = Models::JsonWebKeyCurveName(
                  jsonRoot["policy"]["key_props"]["crv"].get<std::string>());
            }
          }

          if (jsonRoot["policy"].contains("secret_props")
              && !jsonRoot["policy"]["secret_props"].is_null())
          {
            response.Policy.Value().SecretProperties = Models::SecretProperties{};

            if (jsonRoot["policy"]["secret_props"].contains("contentType")
                && !jsonRoot["policy"]["secret_props"]["contentType"].is_null())
            {
              response.Policy.Value().SecretProperties.Value().ContentType
                  = jsonRoot["policy"]["secret_props"]["contentType"].get<std::string>();
            }
          }

          if (jsonRoot["policy"].contains("x509_props")
              && !jsonRoot["policy"]["x509_props"].is_null())
          {
            response.Policy.Value().X509CertificateProperties = Models::X509CertificateProperties{};

            if (jsonRoot["policy"]["x509_props"].contains("subject")
                && !jsonRoot["policy"]["x509_props"]["subject"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Subject
                  = jsonRoot["policy"]["x509_props"]["subject"].get<std::string>();
            }

            if (jsonRoot["policy"]["x509_props"].contains("ekus")
                && !jsonRoot["policy"]["x509_props"]["ekus"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Ekus
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["ekus"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.Policy.Value().X509CertificateProperties.Value().Ekus.Value().emplace_back(
                    std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("sans")
                && !jsonRoot["policy"]["x509_props"]["sans"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().SubjectAlternativeNames
                  = Models::SubjectAlternativeNames{};

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("emails")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["emails"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["emails"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("dns_names")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["dns_names"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["dns_names"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("upns")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["upns"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["upns"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("key_usage")
                && !jsonRoot["policy"]["x509_props"]["key_usage"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().KeyUsage
                  = std::vector<Models::KeyUsageType>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["key_usage"])
              {
                Models::KeyUsageType vectorItem{};

                vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .KeyUsage.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("validity_months")
                && !jsonRoot["policy"]["x509_props"]["validity_months"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().ValidityInMonths
                  = jsonRoot["policy"]["x509_props"]["validity_months"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["x509_props"]["validity_months"].get<std::string>())
                  : jsonRoot["policy"]["x509_props"]["validity_months"].get<std::int32_t>();
            }
          }

          if (jsonRoot["policy"].contains("lifetime_actions")
              && !jsonRoot["policy"]["lifetime_actions"].is_null())
          {
            response.Policy.Value().LifetimeActions = std::vector<Models::LifetimeAction>{};

            for (auto const& jsonItem : jsonRoot["policy"]["lifetime_actions"])
            {
              Models::LifetimeAction vectorItem{};

              if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
              {
                vectorItem.Trigger = Models::Trigger{};

                if (jsonItem["trigger"].contains("lifetime_percentage")
                    && !jsonItem["trigger"]["lifetime_percentage"].is_null())
                {
                  vectorItem.Trigger.Value().LifetimePercentage
                      = jsonItem["trigger"]["lifetime_percentage"].is_string()
                      ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                      : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
                }

                if (jsonItem["trigger"].contains("days_before_expiry")
                    && !jsonItem["trigger"]["days_before_expiry"].is_null())
                {
                  vectorItem.Trigger.Value().DaysBeforeExpiry
                      = jsonItem["trigger"]["days_before_expiry"].is_string()
                      ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                      : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
                }
              }

              if (jsonItem.contains("action") && !jsonItem["action"].is_null())
              {
                vectorItem.Action = Models::Action{};

                if (jsonItem["action"].contains("action_type")
                    && !jsonItem["action"]["action_type"].is_null())
                {
                  vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                      jsonItem["action"]["action_type"].get<std::string>());
                }
              }

              response.Policy.Value().LifetimeActions.Value().emplace_back(std::move(vectorItem));
            }
          }

          if (jsonRoot["policy"].contains("issuer") && !jsonRoot["policy"]["issuer"].is_null())
          {
            response.Policy.Value().IssuerParameters = Models::IssuerParameters{};

            if (jsonRoot["policy"]["issuer"].contains("name")
                && !jsonRoot["policy"]["issuer"]["name"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().Name
                  = jsonRoot["policy"]["issuer"]["name"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cty")
                && !jsonRoot["policy"]["issuer"]["cty"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateType
                  = jsonRoot["policy"]["issuer"]["cty"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cert_transparency")
                && !jsonRoot["policy"]["issuer"]["cert_transparency"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateTransparency
                  = jsonRoot["policy"]["issuer"]["cert_transparency"].get<bool>();
            }
          }

          if (jsonRoot["policy"].contains("attributes")
              && !jsonRoot["policy"]["attributes"].is_null())
          {
            response.Policy.Value().Attributes = Models::CertificateAttributes{};

            if (jsonRoot["policy"]["attributes"].contains("enabled")
                && !jsonRoot["policy"]["attributes"]["enabled"].is_null())
            {
              response.Policy.Value().Attributes.Value().Enabled
                  = jsonRoot["policy"]["attributes"]["enabled"].get<bool>();
            }

            if (jsonRoot["policy"]["attributes"].contains("nbf")
                && !jsonRoot["policy"]["attributes"]["nbf"].is_null())
            {
              response.Policy.Value().Attributes.Value().NotBefore
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["nbf"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["nbf"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["nbf"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("exp")
                && !jsonRoot["policy"]["attributes"]["exp"].is_null())
            {
              response.Policy.Value().Attributes.Value().Expires
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["exp"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["exp"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["exp"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("created")
                && !jsonRoot["policy"]["attributes"]["created"].is_null())
            {
              response.Policy.Value().Attributes.Value().Created
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["created"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["created"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["created"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("updated")
                && !jsonRoot["policy"]["attributes"]["updated"].is_null())
            {
              response.Policy.Value().Attributes.Value().Updated
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["updated"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["updated"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["updated"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("recoverableDays")
                && !jsonRoot["policy"]["attributes"]["recoverableDays"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoverableDays
                  = jsonRoot["policy"]["attributes"]["recoverableDays"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::string>())
                  : jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["attributes"].contains("recoveryLevel")
                && !jsonRoot["policy"]["attributes"]["recoveryLevel"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoveryLevel
                  = Models::DeletionRecoveryLevel(
                      jsonRoot["policy"]["attributes"]["recoveryLevel"].get<std::string>());
            }
          }
        }

        if (jsonRoot.contains("cer") && !jsonRoot["cer"].is_null())
        {
          response.Cer = Core::Convert::Base64Decode(jsonRoot["cer"].get<std::string>());
        }

        if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null())
        {
          response.ContentType = jsonRoot["contentType"].get<std::string>();
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }

        if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null())
        {
          response.Tags = std::map<std::string, std::string>{};

          for (auto const& kv : jsonRoot["tags"].items())
          {
            std::string value{};
            value = kv.value().get<std::string>();
            response.Tags.Value().emplace(kv.key(), value);
          }
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateBundle>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::BackupCertificateResult>
KeyVaultClient::BackupCertificate(const std::string& certificateName, const Core::Context& context)
    const
{
  auto url = m_url;
  url.AppendPath("certificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("backup");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Post, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::BackupCertificateResult response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("value") && !jsonRoot["value"].is_null())
        {
          response.Value
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["value"].get<std::string>());
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::BackupCertificateResult>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateBundle>
KeyVaultClient::RestoreCertificate(
    const Models::CertificateRestoreParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("certificates/restore");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["value"]
        = Core::_internal::Base64Url::Base64UrlEncode(parameters.CertificateBundleBackup);
    jsonBody = jsonRoot.dump();
  }

  Core::IO::MemoryBodyStream requestBody(
      reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());

  Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody);

  request.SetHeader("Content-Type", "application/json");
  request.SetHeader("Accept", "application/json");

  request.SetHeader("Content-Length", std::to_string(requestBody.Length()));

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

        if (jsonRoot.contains("sid") && !jsonRoot["sid"].is_null())
        {
          response.Sid = jsonRoot["sid"].get<std::string>();
        }

        if (jsonRoot.contains("x5t") && !jsonRoot["x5t"].is_null())
        {
          response.X509Thumbprint
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["x5t"].get<std::string>());
        }

        if (jsonRoot.contains("policy") && !jsonRoot["policy"].is_null())
        {
          response.Policy = Models::CertificatePolicy{};

          if (jsonRoot["policy"].contains("id") && !jsonRoot["policy"]["id"].is_null())
          {
            response.Policy.Value().Id = jsonRoot["policy"]["id"].get<std::string>();
          }

          if (jsonRoot["policy"].contains("key_props")
              && !jsonRoot["policy"]["key_props"].is_null())
          {
            response.Policy.Value().KeyProperties = Models::KeyProperties{};

            if (jsonRoot["policy"]["key_props"].contains("exportable")
                && !jsonRoot["policy"]["key_props"]["exportable"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Exportable
                  = jsonRoot["policy"]["key_props"]["exportable"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("kty")
                && !jsonRoot["policy"]["key_props"]["kty"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeyType = Models::JsonWebKeyType(
                  jsonRoot["policy"]["key_props"]["kty"].get<std::string>());
            }

            if (jsonRoot["policy"]["key_props"].contains("key_size")
                && !jsonRoot["policy"]["key_props"]["key_size"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeySize
                  = jsonRoot["policy"]["key_props"]["key_size"].is_string()
                  ? std::stoi(jsonRoot["policy"]["key_props"]["key_size"].get<std::string>())
                  : jsonRoot["policy"]["key_props"]["key_size"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["key_props"].contains("reuse_key")
                && !jsonRoot["policy"]["key_props"]["reuse_key"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().ReuseKey
                  = jsonRoot["policy"]["key_props"]["reuse_key"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("crv")
                && !jsonRoot["policy"]["key_props"]["crv"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Curve = Models::JsonWebKeyCurveName(
                  jsonRoot["policy"]["key_props"]["crv"].get<std::string>());
            }
          }

          if (jsonRoot["policy"].contains("secret_props")
              && !jsonRoot["policy"]["secret_props"].is_null())
          {
            response.Policy.Value().SecretProperties = Models::SecretProperties{};

            if (jsonRoot["policy"]["secret_props"].contains("contentType")
                && !jsonRoot["policy"]["secret_props"]["contentType"].is_null())
            {
              response.Policy.Value().SecretProperties.Value().ContentType
                  = jsonRoot["policy"]["secret_props"]["contentType"].get<std::string>();
            }
          }

          if (jsonRoot["policy"].contains("x509_props")
              && !jsonRoot["policy"]["x509_props"].is_null())
          {
            response.Policy.Value().X509CertificateProperties = Models::X509CertificateProperties{};

            if (jsonRoot["policy"]["x509_props"].contains("subject")
                && !jsonRoot["policy"]["x509_props"]["subject"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Subject
                  = jsonRoot["policy"]["x509_props"]["subject"].get<std::string>();
            }

            if (jsonRoot["policy"]["x509_props"].contains("ekus")
                && !jsonRoot["policy"]["x509_props"]["ekus"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Ekus
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["ekus"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.Policy.Value().X509CertificateProperties.Value().Ekus.Value().emplace_back(
                    std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("sans")
                && !jsonRoot["policy"]["x509_props"]["sans"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().SubjectAlternativeNames
                  = Models::SubjectAlternativeNames{};

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("emails")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["emails"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["emails"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("dns_names")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["dns_names"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["dns_names"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("upns")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["upns"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["upns"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("key_usage")
                && !jsonRoot["policy"]["x509_props"]["key_usage"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().KeyUsage
                  = std::vector<Models::KeyUsageType>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["key_usage"])
              {
                Models::KeyUsageType vectorItem{};

                vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .KeyUsage.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("validity_months")
                && !jsonRoot["policy"]["x509_props"]["validity_months"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().ValidityInMonths
                  = jsonRoot["policy"]["x509_props"]["validity_months"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["x509_props"]["validity_months"].get<std::string>())
                  : jsonRoot["policy"]["x509_props"]["validity_months"].get<std::int32_t>();
            }
          }

          if (jsonRoot["policy"].contains("lifetime_actions")
              && !jsonRoot["policy"]["lifetime_actions"].is_null())
          {
            response.Policy.Value().LifetimeActions = std::vector<Models::LifetimeAction>{};

            for (auto const& jsonItem : jsonRoot["policy"]["lifetime_actions"])
            {
              Models::LifetimeAction vectorItem{};

              if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
              {
                vectorItem.Trigger = Models::Trigger{};

                if (jsonItem["trigger"].contains("lifetime_percentage")
                    && !jsonItem["trigger"]["lifetime_percentage"].is_null())
                {
                  vectorItem.Trigger.Value().LifetimePercentage
                      = jsonItem["trigger"]["lifetime_percentage"].is_string()
                      ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                      : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
                }

                if (jsonItem["trigger"].contains("days_before_expiry")
                    && !jsonItem["trigger"]["days_before_expiry"].is_null())
                {
                  vectorItem.Trigger.Value().DaysBeforeExpiry
                      = jsonItem["trigger"]["days_before_expiry"].is_string()
                      ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                      : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
                }
              }

              if (jsonItem.contains("action") && !jsonItem["action"].is_null())
              {
                vectorItem.Action = Models::Action{};

                if (jsonItem["action"].contains("action_type")
                    && !jsonItem["action"]["action_type"].is_null())
                {
                  vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                      jsonItem["action"]["action_type"].get<std::string>());
                }
              }

              response.Policy.Value().LifetimeActions.Value().emplace_back(std::move(vectorItem));
            }
          }

          if (jsonRoot["policy"].contains("issuer") && !jsonRoot["policy"]["issuer"].is_null())
          {
            response.Policy.Value().IssuerParameters = Models::IssuerParameters{};

            if (jsonRoot["policy"]["issuer"].contains("name")
                && !jsonRoot["policy"]["issuer"]["name"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().Name
                  = jsonRoot["policy"]["issuer"]["name"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cty")
                && !jsonRoot["policy"]["issuer"]["cty"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateType
                  = jsonRoot["policy"]["issuer"]["cty"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cert_transparency")
                && !jsonRoot["policy"]["issuer"]["cert_transparency"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateTransparency
                  = jsonRoot["policy"]["issuer"]["cert_transparency"].get<bool>();
            }
          }

          if (jsonRoot["policy"].contains("attributes")
              && !jsonRoot["policy"]["attributes"].is_null())
          {
            response.Policy.Value().Attributes = Models::CertificateAttributes{};

            if (jsonRoot["policy"]["attributes"].contains("enabled")
                && !jsonRoot["policy"]["attributes"]["enabled"].is_null())
            {
              response.Policy.Value().Attributes.Value().Enabled
                  = jsonRoot["policy"]["attributes"]["enabled"].get<bool>();
            }

            if (jsonRoot["policy"]["attributes"].contains("nbf")
                && !jsonRoot["policy"]["attributes"]["nbf"].is_null())
            {
              response.Policy.Value().Attributes.Value().NotBefore
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["nbf"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["nbf"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["nbf"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("exp")
                && !jsonRoot["policy"]["attributes"]["exp"].is_null())
            {
              response.Policy.Value().Attributes.Value().Expires
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["exp"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["exp"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["exp"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("created")
                && !jsonRoot["policy"]["attributes"]["created"].is_null())
            {
              response.Policy.Value().Attributes.Value().Created
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["created"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["created"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["created"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("updated")
                && !jsonRoot["policy"]["attributes"]["updated"].is_null())
            {
              response.Policy.Value().Attributes.Value().Updated
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["updated"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["updated"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["updated"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("recoverableDays")
                && !jsonRoot["policy"]["attributes"]["recoverableDays"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoverableDays
                  = jsonRoot["policy"]["attributes"]["recoverableDays"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::string>())
                  : jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["attributes"].contains("recoveryLevel")
                && !jsonRoot["policy"]["attributes"]["recoveryLevel"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoveryLevel
                  = Models::DeletionRecoveryLevel(
                      jsonRoot["policy"]["attributes"]["recoveryLevel"].get<std::string>());
            }
          }
        }

        if (jsonRoot.contains("cer") && !jsonRoot["cer"].is_null())
        {
          response.Cer = Core::Convert::Base64Decode(jsonRoot["cer"].get<std::string>());
        }

        if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null())
        {
          response.ContentType = jsonRoot["contentType"].get<std::string>();
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }

        if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null())
        {
          response.Tags = std::map<std::string, std::string>{};

          for (auto const& kv : jsonRoot["tags"].items())
          {
            std::string value{};
            value = kv.value().get<std::string>();
            response.Tags.Value().emplace(kv.key(), value);
          }
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateBundle>(std::move(response), std::move(rawResponse));
}

GetDeletedCertificatesPagedResponse KeyVaultClient::GetDeletedCertificates(
    const KeyVaultClientGetDeletedCertificatesOptions& options,
    const Core::Context& context) const
{
  Core::Url url;
  if (options.NextPageToken.empty())
  {
    url = m_url;
    url.AppendPath("deletedcertificates");

    url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));
    if (options.Maxresults.HasValue())
    {
      url.AppendQueryParameter("maxresults", std::to_string(options.Maxresults.Value()));
    }

    if (options.IncludePending.HasValue())
    {
      url.AppendQueryParameter("includePending", options.IncludePending.Value() ? "true" : "false");
    }
  }
  else
  {
    if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0)
    {
      url = Core::Url(options.NextPageToken);
      if (url.GetPort() == 0 && m_url.GetPort() != 0 && url.GetHost() == m_url.GetHost())
      {
        url.SetPort(m_url.GetPort());
      }
    }
    else
    {
      url = Core::Url(
          m_url.GetScheme() + "://" + m_url.GetHost() + ':' + std::to_string(m_url.GetPort()) + '/'
          + (options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1)
                                             : options.NextPageToken));
    }

    const auto qps = url.GetQueryParameters();
    if (qps.find("api-version") != qps.cend())
    {
      url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));
    }
  }

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  GetDeletedCertificatesPagedResponse response{};
  response.m_client = std::make_shared<KeyVaultClient>(*this);
  response.m_options = options;
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());
        if (jsonRoot.contains("nextLink") && !jsonRoot["nextLink"].is_null())
        {
          response.NextPageToken = jsonRoot["nextLink"].get<std::string>();
        }

        if (jsonRoot.contains("value") && !jsonRoot["value"].is_null())
        {
          response.Value = std::vector<Models::DeletedCertificateItem>{};

          for (auto const& jsonItem : jsonRoot["value"])
          {
            Models::DeletedCertificateItem vectorItem{};

            if (jsonItem.contains("id") && !jsonItem["id"].is_null())
            {
              vectorItem.Id = jsonItem["id"].get<std::string>();
            }

            if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null())
            {
              vectorItem.Attributes = Models::CertificateAttributes{};

              if (jsonItem["attributes"].contains("enabled")
                  && !jsonItem["attributes"]["enabled"].is_null())
              {
                vectorItem.Attributes.Value().Enabled
                    = jsonItem["attributes"]["enabled"].get<bool>();
              }

              if (jsonItem["attributes"].contains("nbf")
                  && !jsonItem["attributes"]["nbf"].is_null())
              {
                vectorItem.Attributes.Value().NotBefore
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["nbf"].is_string()
                            ? std::stoll(jsonItem["attributes"]["nbf"].get<std::string>())
                            : jsonItem["attributes"]["nbf"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("exp")
                  && !jsonItem["attributes"]["exp"].is_null())
              {
                vectorItem.Attributes.Value().Expires
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["exp"].is_string()
                            ? std::stoll(jsonItem["attributes"]["exp"].get<std::string>())
                            : jsonItem["attributes"]["exp"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("created")
                  && !jsonItem["attributes"]["created"].is_null())
              {
                vectorItem.Attributes.Value().Created
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["created"].is_string()
                            ? std::stoll(jsonItem["attributes"]["created"].get<std::string>())
                            : jsonItem["attributes"]["created"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("updated")
                  && !jsonItem["attributes"]["updated"].is_null())
              {
                vectorItem.Attributes.Value().Updated
                    = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                        jsonItem["attributes"]["updated"].is_string()
                            ? std::stoll(jsonItem["attributes"]["updated"].get<std::string>())
                            : jsonItem["attributes"]["updated"].get<std::int64_t>());
              }

              if (jsonItem["attributes"].contains("recoverableDays")
                  && !jsonItem["attributes"]["recoverableDays"].is_null())
              {
                vectorItem.Attributes.Value().RecoverableDays
                    = jsonItem["attributes"]["recoverableDays"].is_string()
                    ? std::stoi(jsonItem["attributes"]["recoverableDays"].get<std::string>())
                    : jsonItem["attributes"]["recoverableDays"].get<std::int32_t>();
              }

              if (jsonItem["attributes"].contains("recoveryLevel")
                  && !jsonItem["attributes"]["recoveryLevel"].is_null())
              {
                vectorItem.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                    jsonItem["attributes"]["recoveryLevel"].get<std::string>());
              }
            }

            if (jsonItem.contains("tags") && !jsonItem["tags"].is_null())
            {
              vectorItem.Tags = std::map<std::string, std::string>{};

              for (auto const& kv : jsonItem["tags"].items())
              {
                std::string value{};
                value = kv.value().get<std::string>();
                vectorItem.Tags.Value().emplace(kv.key(), value);
              }
            }

            if (jsonItem.contains("x5t") && !jsonItem["x5t"].is_null())
            {
              vectorItem.X509Thumbprint
                  = Core::_internal::Base64Url::Base64UrlDecode(jsonItem["x5t"].get<std::string>());
            }

            if (jsonItem.contains("recoveryId") && !jsonItem["recoveryId"].is_null())
            {
              vectorItem.RecoveryId = jsonItem["recoveryId"].get<std::string>();
            }

            if (jsonItem.contains("scheduledPurgeDate")
                && !jsonItem["scheduledPurgeDate"].is_null())
            {
              vectorItem.ScheduledPurgeDate
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonItem["scheduledPurgeDate"].is_string()
                          ? std::stoll(jsonItem["scheduledPurgeDate"].get<std::string>())
                          : jsonItem["scheduledPurgeDate"].get<std::int64_t>());
            }

            if (jsonItem.contains("deletedDate") && !jsonItem["deletedDate"].is_null())
            {
              vectorItem.DeletedDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                  jsonItem["deletedDate"].is_string()
                      ? std::stoll(jsonItem["deletedDate"].get<std::string>())
                      : jsonItem["deletedDate"].get<std::int64_t>());
            }

            response.Value.Value().emplace_back(std::move(vectorItem));
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  response.RawResponse = std::move(rawResponse);

  return response;
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::DeletedCertificateBundle>
KeyVaultClient::GetDeletedCertificate(
    const std::string& certificateName,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("deletedcertificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Get, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::DeletedCertificateBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

        if (jsonRoot.contains("sid") && !jsonRoot["sid"].is_null())
        {
          response.Sid = jsonRoot["sid"].get<std::string>();
        }

        if (jsonRoot.contains("x5t") && !jsonRoot["x5t"].is_null())
        {
          response.X509Thumbprint
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["x5t"].get<std::string>());
        }

        if (jsonRoot.contains("policy") && !jsonRoot["policy"].is_null())
        {
          response.Policy = Models::CertificatePolicy{};

          if (jsonRoot["policy"].contains("id") && !jsonRoot["policy"]["id"].is_null())
          {
            response.Policy.Value().Id = jsonRoot["policy"]["id"].get<std::string>();
          }

          if (jsonRoot["policy"].contains("key_props")
              && !jsonRoot["policy"]["key_props"].is_null())
          {
            response.Policy.Value().KeyProperties = Models::KeyProperties{};

            if (jsonRoot["policy"]["key_props"].contains("exportable")
                && !jsonRoot["policy"]["key_props"]["exportable"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Exportable
                  = jsonRoot["policy"]["key_props"]["exportable"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("kty")
                && !jsonRoot["policy"]["key_props"]["kty"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeyType = Models::JsonWebKeyType(
                  jsonRoot["policy"]["key_props"]["kty"].get<std::string>());
            }

            if (jsonRoot["policy"]["key_props"].contains("key_size")
                && !jsonRoot["policy"]["key_props"]["key_size"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeySize
                  = jsonRoot["policy"]["key_props"]["key_size"].is_string()
                  ? std::stoi(jsonRoot["policy"]["key_props"]["key_size"].get<std::string>())
                  : jsonRoot["policy"]["key_props"]["key_size"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["key_props"].contains("reuse_key")
                && !jsonRoot["policy"]["key_props"]["reuse_key"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().ReuseKey
                  = jsonRoot["policy"]["key_props"]["reuse_key"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("crv")
                && !jsonRoot["policy"]["key_props"]["crv"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Curve = Models::JsonWebKeyCurveName(
                  jsonRoot["policy"]["key_props"]["crv"].get<std::string>());
            }
          }

          if (jsonRoot["policy"].contains("secret_props")
              && !jsonRoot["policy"]["secret_props"].is_null())
          {
            response.Policy.Value().SecretProperties = Models::SecretProperties{};

            if (jsonRoot["policy"]["secret_props"].contains("contentType")
                && !jsonRoot["policy"]["secret_props"]["contentType"].is_null())
            {
              response.Policy.Value().SecretProperties.Value().ContentType
                  = jsonRoot["policy"]["secret_props"]["contentType"].get<std::string>();
            }
          }

          if (jsonRoot["policy"].contains("x509_props")
              && !jsonRoot["policy"]["x509_props"].is_null())
          {
            response.Policy.Value().X509CertificateProperties = Models::X509CertificateProperties{};

            if (jsonRoot["policy"]["x509_props"].contains("subject")
                && !jsonRoot["policy"]["x509_props"]["subject"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Subject
                  = jsonRoot["policy"]["x509_props"]["subject"].get<std::string>();
            }

            if (jsonRoot["policy"]["x509_props"].contains("ekus")
                && !jsonRoot["policy"]["x509_props"]["ekus"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Ekus
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["ekus"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.Policy.Value().X509CertificateProperties.Value().Ekus.Value().emplace_back(
                    std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("sans")
                && !jsonRoot["policy"]["x509_props"]["sans"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().SubjectAlternativeNames
                  = Models::SubjectAlternativeNames{};

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("emails")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["emails"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["emails"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("dns_names")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["dns_names"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["dns_names"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("upns")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["upns"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["upns"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("key_usage")
                && !jsonRoot["policy"]["x509_props"]["key_usage"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().KeyUsage
                  = std::vector<Models::KeyUsageType>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["key_usage"])
              {
                Models::KeyUsageType vectorItem{};

                vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .KeyUsage.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("validity_months")
                && !jsonRoot["policy"]["x509_props"]["validity_months"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().ValidityInMonths
                  = jsonRoot["policy"]["x509_props"]["validity_months"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["x509_props"]["validity_months"].get<std::string>())
                  : jsonRoot["policy"]["x509_props"]["validity_months"].get<std::int32_t>();
            }
          }

          if (jsonRoot["policy"].contains("lifetime_actions")
              && !jsonRoot["policy"]["lifetime_actions"].is_null())
          {
            response.Policy.Value().LifetimeActions = std::vector<Models::LifetimeAction>{};

            for (auto const& jsonItem : jsonRoot["policy"]["lifetime_actions"])
            {
              Models::LifetimeAction vectorItem{};

              if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
              {
                vectorItem.Trigger = Models::Trigger{};

                if (jsonItem["trigger"].contains("lifetime_percentage")
                    && !jsonItem["trigger"]["lifetime_percentage"].is_null())
                {
                  vectorItem.Trigger.Value().LifetimePercentage
                      = jsonItem["trigger"]["lifetime_percentage"].is_string()
                      ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                      : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
                }

                if (jsonItem["trigger"].contains("days_before_expiry")
                    && !jsonItem["trigger"]["days_before_expiry"].is_null())
                {
                  vectorItem.Trigger.Value().DaysBeforeExpiry
                      = jsonItem["trigger"]["days_before_expiry"].is_string()
                      ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                      : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
                }
              }

              if (jsonItem.contains("action") && !jsonItem["action"].is_null())
              {
                vectorItem.Action = Models::Action{};

                if (jsonItem["action"].contains("action_type")
                    && !jsonItem["action"]["action_type"].is_null())
                {
                  vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                      jsonItem["action"]["action_type"].get<std::string>());
                }
              }

              response.Policy.Value().LifetimeActions.Value().emplace_back(std::move(vectorItem));
            }
          }

          if (jsonRoot["policy"].contains("issuer") && !jsonRoot["policy"]["issuer"].is_null())
          {
            response.Policy.Value().IssuerParameters = Models::IssuerParameters{};

            if (jsonRoot["policy"]["issuer"].contains("name")
                && !jsonRoot["policy"]["issuer"]["name"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().Name
                  = jsonRoot["policy"]["issuer"]["name"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cty")
                && !jsonRoot["policy"]["issuer"]["cty"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateType
                  = jsonRoot["policy"]["issuer"]["cty"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cert_transparency")
                && !jsonRoot["policy"]["issuer"]["cert_transparency"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateTransparency
                  = jsonRoot["policy"]["issuer"]["cert_transparency"].get<bool>();
            }
          }

          if (jsonRoot["policy"].contains("attributes")
              && !jsonRoot["policy"]["attributes"].is_null())
          {
            response.Policy.Value().Attributes = Models::CertificateAttributes{};

            if (jsonRoot["policy"]["attributes"].contains("enabled")
                && !jsonRoot["policy"]["attributes"]["enabled"].is_null())
            {
              response.Policy.Value().Attributes.Value().Enabled
                  = jsonRoot["policy"]["attributes"]["enabled"].get<bool>();
            }

            if (jsonRoot["policy"]["attributes"].contains("nbf")
                && !jsonRoot["policy"]["attributes"]["nbf"].is_null())
            {
              response.Policy.Value().Attributes.Value().NotBefore
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["nbf"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["nbf"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["nbf"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("exp")
                && !jsonRoot["policy"]["attributes"]["exp"].is_null())
            {
              response.Policy.Value().Attributes.Value().Expires
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["exp"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["exp"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["exp"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("created")
                && !jsonRoot["policy"]["attributes"]["created"].is_null())
            {
              response.Policy.Value().Attributes.Value().Created
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["created"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["created"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["created"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("updated")
                && !jsonRoot["policy"]["attributes"]["updated"].is_null())
            {
              response.Policy.Value().Attributes.Value().Updated
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["updated"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["updated"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["updated"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("recoverableDays")
                && !jsonRoot["policy"]["attributes"]["recoverableDays"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoverableDays
                  = jsonRoot["policy"]["attributes"]["recoverableDays"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::string>())
                  : jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["attributes"].contains("recoveryLevel")
                && !jsonRoot["policy"]["attributes"]["recoveryLevel"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoveryLevel
                  = Models::DeletionRecoveryLevel(
                      jsonRoot["policy"]["attributes"]["recoveryLevel"].get<std::string>());
            }
          }
        }

        if (jsonRoot.contains("cer") && !jsonRoot["cer"].is_null())
        {
          response.Cer = Core::Convert::Base64Decode(jsonRoot["cer"].get<std::string>());
        }

        if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null())
        {
          response.ContentType = jsonRoot["contentType"].get<std::string>();
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }

        if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null())
        {
          response.Tags = std::map<std::string, std::string>{};

          for (auto const& kv : jsonRoot["tags"].items())
          {
            std::string value{};
            value = kv.value().get<std::string>();
            response.Tags.Value().emplace(kv.key(), value);
          }
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }

        if (jsonRoot.contains("recoveryId") && !jsonRoot["recoveryId"].is_null())
        {
          response.RecoveryId = jsonRoot["recoveryId"].get<std::string>();
        }

        if (jsonRoot.contains("scheduledPurgeDate") && !jsonRoot["scheduledPurgeDate"].is_null())
        {
          response.ScheduledPurgeDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
              jsonRoot["scheduledPurgeDate"].is_string()
                  ? std::stoll(jsonRoot["scheduledPurgeDate"].get<std::string>())
                  : jsonRoot["scheduledPurgeDate"].get<std::int64_t>());
        }

        if (jsonRoot.contains("deletedDate") && !jsonRoot["deletedDate"].is_null())
        {
          response.DeletedDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
              jsonRoot["deletedDate"].is_string()
                  ? std::stoll(jsonRoot["deletedDate"].get<std::string>())
                  : jsonRoot["deletedDate"].get<std::int64_t>());
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::DeletedCertificateBundle>(std::move(response), std::move(rawResponse));
}

Azure::Response<
    Azure::Security::KeyVault::Certificates::_detail::Models::PurgeDeletedCertificateResult>
KeyVaultClient::PurgeDeletedCertificate(
    const std::string& certificateName,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("deletedcertificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Delete, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::NoContent)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::PurgeDeletedCertificateResult response{};

  return Response<Models::PurgeDeletedCertificateResult>(
      std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Certificates::_detail::Models::CertificateBundle>
KeyVaultClient::RecoverDeletedCertificate(
    const std::string& certificateName,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("deletedcertificates/");
  if (certificateName.empty())
  {
    throw std::invalid_argument("Parameter 'certificateName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(certificateName));
  url.AppendPath("recover");

  url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion));

  Core::Http::Request request(Core::Http::HttpMethod::Post, url);

  request.SetHeader("Accept", "application/json");

  auto rawResponse = m_pipeline->Send(request, context);
  const auto httpStatusCode = rawResponse->GetStatusCode();

  if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
  {
    throw Core::RequestFailedException(rawResponse);
  }

  Models::CertificateBundle response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        if (jsonRoot.contains("id") && !jsonRoot["id"].is_null())
        {
          response.Id = jsonRoot["id"].get<std::string>();
        }

        if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

        if (jsonRoot.contains("sid") && !jsonRoot["sid"].is_null())
        {
          response.Sid = jsonRoot["sid"].get<std::string>();
        }

        if (jsonRoot.contains("x5t") && !jsonRoot["x5t"].is_null())
        {
          response.X509Thumbprint
              = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["x5t"].get<std::string>());
        }

        if (jsonRoot.contains("policy") && !jsonRoot["policy"].is_null())
        {
          response.Policy = Models::CertificatePolicy{};

          if (jsonRoot["policy"].contains("id") && !jsonRoot["policy"]["id"].is_null())
          {
            response.Policy.Value().Id = jsonRoot["policy"]["id"].get<std::string>();
          }

          if (jsonRoot["policy"].contains("key_props")
              && !jsonRoot["policy"]["key_props"].is_null())
          {
            response.Policy.Value().KeyProperties = Models::KeyProperties{};

            if (jsonRoot["policy"]["key_props"].contains("exportable")
                && !jsonRoot["policy"]["key_props"]["exportable"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Exportable
                  = jsonRoot["policy"]["key_props"]["exportable"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("kty")
                && !jsonRoot["policy"]["key_props"]["kty"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeyType = Models::JsonWebKeyType(
                  jsonRoot["policy"]["key_props"]["kty"].get<std::string>());
            }

            if (jsonRoot["policy"]["key_props"].contains("key_size")
                && !jsonRoot["policy"]["key_props"]["key_size"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().KeySize
                  = jsonRoot["policy"]["key_props"]["key_size"].is_string()
                  ? std::stoi(jsonRoot["policy"]["key_props"]["key_size"].get<std::string>())
                  : jsonRoot["policy"]["key_props"]["key_size"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["key_props"].contains("reuse_key")
                && !jsonRoot["policy"]["key_props"]["reuse_key"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().ReuseKey
                  = jsonRoot["policy"]["key_props"]["reuse_key"].get<bool>();
            }

            if (jsonRoot["policy"]["key_props"].contains("crv")
                && !jsonRoot["policy"]["key_props"]["crv"].is_null())
            {
              response.Policy.Value().KeyProperties.Value().Curve = Models::JsonWebKeyCurveName(
                  jsonRoot["policy"]["key_props"]["crv"].get<std::string>());
            }
          }

          if (jsonRoot["policy"].contains("secret_props")
              && !jsonRoot["policy"]["secret_props"].is_null())
          {
            response.Policy.Value().SecretProperties = Models::SecretProperties{};

            if (jsonRoot["policy"]["secret_props"].contains("contentType")
                && !jsonRoot["policy"]["secret_props"]["contentType"].is_null())
            {
              response.Policy.Value().SecretProperties.Value().ContentType
                  = jsonRoot["policy"]["secret_props"]["contentType"].get<std::string>();
            }
          }

          if (jsonRoot["policy"].contains("x509_props")
              && !jsonRoot["policy"]["x509_props"].is_null())
          {
            response.Policy.Value().X509CertificateProperties = Models::X509CertificateProperties{};

            if (jsonRoot["policy"]["x509_props"].contains("subject")
                && !jsonRoot["policy"]["x509_props"]["subject"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Subject
                  = jsonRoot["policy"]["x509_props"]["subject"].get<std::string>();
            }

            if (jsonRoot["policy"]["x509_props"].contains("ekus")
                && !jsonRoot["policy"]["x509_props"]["ekus"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().Ekus
                  = std::vector<std::string>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["ekus"])
              {
                std::string vectorItem{};

                vectorItem = jsonItem.get<std::string>();

                response.Policy.Value().X509CertificateProperties.Value().Ekus.Value().emplace_back(
                    std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("sans")
                && !jsonRoot["policy"]["x509_props"]["sans"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().SubjectAlternativeNames
                  = Models::SubjectAlternativeNames{};

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("emails")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["emails"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Emails
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["emails"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Emails.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("dns_names")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["dns_names"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .DnsNames
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["dns_names"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .DnsNames.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }

              if (jsonRoot["policy"]["x509_props"]["sans"].contains("upns")
                  && !jsonRoot["policy"]["x509_props"]["sans"]["upns"].is_null())
              {
                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .SubjectAlternativeNames.Value()
                    .Upns
                    = std::vector<std::string>{};

                for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["sans"]["upns"])
                {
                  std::string vectorItem{};

                  vectorItem = jsonItem.get<std::string>();

                  response.Policy.Value()
                      .X509CertificateProperties.Value()
                      .SubjectAlternativeNames.Value()
                      .Upns.Value()
                      .emplace_back(std::move(vectorItem));
                }
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("key_usage")
                && !jsonRoot["policy"]["x509_props"]["key_usage"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().KeyUsage
                  = std::vector<Models::KeyUsageType>{};

              for (auto const& jsonItem : jsonRoot["policy"]["x509_props"]["key_usage"])
              {
                Models::KeyUsageType vectorItem{};

                vectorItem = Models::KeyUsageType(jsonItem.get<std::string>());

                response.Policy.Value()
                    .X509CertificateProperties.Value()
                    .KeyUsage.Value()
                    .emplace_back(std::move(vectorItem));
              }
            }

            if (jsonRoot["policy"]["x509_props"].contains("validity_months")
                && !jsonRoot["policy"]["x509_props"]["validity_months"].is_null())
            {
              response.Policy.Value().X509CertificateProperties.Value().ValidityInMonths
                  = jsonRoot["policy"]["x509_props"]["validity_months"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["x509_props"]["validity_months"].get<std::string>())
                  : jsonRoot["policy"]["x509_props"]["validity_months"].get<std::int32_t>();
            }
          }

          if (jsonRoot["policy"].contains("lifetime_actions")
              && !jsonRoot["policy"]["lifetime_actions"].is_null())
          {
            response.Policy.Value().LifetimeActions = std::vector<Models::LifetimeAction>{};

            for (auto const& jsonItem : jsonRoot["policy"]["lifetime_actions"])
            {
              Models::LifetimeAction vectorItem{};

              if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null())
              {
                vectorItem.Trigger = Models::Trigger{};

                if (jsonItem["trigger"].contains("lifetime_percentage")
                    && !jsonItem["trigger"]["lifetime_percentage"].is_null())
                {
                  vectorItem.Trigger.Value().LifetimePercentage
                      = jsonItem["trigger"]["lifetime_percentage"].is_string()
                      ? std::stoi(jsonItem["trigger"]["lifetime_percentage"].get<std::string>())
                      : jsonItem["trigger"]["lifetime_percentage"].get<std::int32_t>();
                }

                if (jsonItem["trigger"].contains("days_before_expiry")
                    && !jsonItem["trigger"]["days_before_expiry"].is_null())
                {
                  vectorItem.Trigger.Value().DaysBeforeExpiry
                      = jsonItem["trigger"]["days_before_expiry"].is_string()
                      ? std::stoi(jsonItem["trigger"]["days_before_expiry"].get<std::string>())
                      : jsonItem["trigger"]["days_before_expiry"].get<std::int32_t>();
                }
              }

              if (jsonItem.contains("action") && !jsonItem["action"].is_null())
              {
                vectorItem.Action = Models::Action{};

                if (jsonItem["action"].contains("action_type")
                    && !jsonItem["action"]["action_type"].is_null())
                {
                  vectorItem.Action.Value().ActionType = Models::CertificatePolicyAction(
                      jsonItem["action"]["action_type"].get<std::string>());
                }
              }

              response.Policy.Value().LifetimeActions.Value().emplace_back(std::move(vectorItem));
            }
          }

          if (jsonRoot["policy"].contains("issuer") && !jsonRoot["policy"]["issuer"].is_null())
          {
            response.Policy.Value().IssuerParameters = Models::IssuerParameters{};

            if (jsonRoot["policy"]["issuer"].contains("name")
                && !jsonRoot["policy"]["issuer"]["name"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().Name
                  = jsonRoot["policy"]["issuer"]["name"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cty")
                && !jsonRoot["policy"]["issuer"]["cty"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateType
                  = jsonRoot["policy"]["issuer"]["cty"].get<std::string>();
            }

            if (jsonRoot["policy"]["issuer"].contains("cert_transparency")
                && !jsonRoot["policy"]["issuer"]["cert_transparency"].is_null())
            {
              response.Policy.Value().IssuerParameters.Value().CertificateTransparency
                  = jsonRoot["policy"]["issuer"]["cert_transparency"].get<bool>();
            }
          }

          if (jsonRoot["policy"].contains("attributes")
              && !jsonRoot["policy"]["attributes"].is_null())
          {
            response.Policy.Value().Attributes = Models::CertificateAttributes{};

            if (jsonRoot["policy"]["attributes"].contains("enabled")
                && !jsonRoot["policy"]["attributes"]["enabled"].is_null())
            {
              response.Policy.Value().Attributes.Value().Enabled
                  = jsonRoot["policy"]["attributes"]["enabled"].get<bool>();
            }

            if (jsonRoot["policy"]["attributes"].contains("nbf")
                && !jsonRoot["policy"]["attributes"]["nbf"].is_null())
            {
              response.Policy.Value().Attributes.Value().NotBefore
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["nbf"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["nbf"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["nbf"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("exp")
                && !jsonRoot["policy"]["attributes"]["exp"].is_null())
            {
              response.Policy.Value().Attributes.Value().Expires
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["exp"].is_string()
                          ? std::stoll(jsonRoot["policy"]["attributes"]["exp"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["exp"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("created")
                && !jsonRoot["policy"]["attributes"]["created"].is_null())
            {
              response.Policy.Value().Attributes.Value().Created
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["created"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["created"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["created"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("updated")
                && !jsonRoot["policy"]["attributes"]["updated"].is_null())
            {
              response.Policy.Value().Attributes.Value().Updated
                  = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                      jsonRoot["policy"]["attributes"]["updated"].is_string()
                          ? std::stoll(
                              jsonRoot["policy"]["attributes"]["updated"].get<std::string>())
                          : jsonRoot["policy"]["attributes"]["updated"].get<std::int64_t>());
            }

            if (jsonRoot["policy"]["attributes"].contains("recoverableDays")
                && !jsonRoot["policy"]["attributes"]["recoverableDays"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoverableDays
                  = jsonRoot["policy"]["attributes"]["recoverableDays"].is_string()
                  ? std::stoi(
                      jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::string>())
                  : jsonRoot["policy"]["attributes"]["recoverableDays"].get<std::int32_t>();
            }

            if (jsonRoot["policy"]["attributes"].contains("recoveryLevel")
                && !jsonRoot["policy"]["attributes"]["recoveryLevel"].is_null())
            {
              response.Policy.Value().Attributes.Value().RecoveryLevel
                  = Models::DeletionRecoveryLevel(
                      jsonRoot["policy"]["attributes"]["recoveryLevel"].get<std::string>());
            }
          }
        }

        if (jsonRoot.contains("cer") && !jsonRoot["cer"].is_null())
        {
          response.Cer = Core::Convert::Base64Decode(jsonRoot["cer"].get<std::string>());
        }

        if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null())
        {
          response.ContentType = jsonRoot["contentType"].get<std::string>();
        }

        if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null())
        {
          response.Attributes = Models::CertificateAttributes{};

          if (jsonRoot["attributes"].contains("enabled")
              && !jsonRoot["attributes"]["enabled"].is_null())
          {
            response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get<bool>();
          }

          if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null())
          {
            response.Attributes.Value().NotBefore
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["nbf"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["nbf"].get<std::string>())
                        : jsonRoot["attributes"]["nbf"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null())
          {
            response.Attributes.Value().Expires
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["exp"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["exp"].get<std::string>())
                        : jsonRoot["attributes"]["exp"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("created")
              && !jsonRoot["attributes"]["created"].is_null())
          {
            response.Attributes.Value().Created
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["created"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["created"].get<std::string>())
                        : jsonRoot["attributes"]["created"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("updated")
              && !jsonRoot["attributes"]["updated"].is_null())
          {
            response.Attributes.Value().Updated
                = Core::_internal::PosixTimeConverter::PosixTimeToDateTime(
                    jsonRoot["attributes"]["updated"].is_string()
                        ? std::stoll(jsonRoot["attributes"]["updated"].get<std::string>())
                        : jsonRoot["attributes"]["updated"].get<std::int64_t>());
          }

          if (jsonRoot["attributes"].contains("recoverableDays")
              && !jsonRoot["attributes"]["recoverableDays"].is_null())
          {
            response.Attributes.Value().RecoverableDays
                = jsonRoot["attributes"]["recoverableDays"].is_string()
                ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get<std::string>())
                : jsonRoot["attributes"]["recoverableDays"].get<std::int32_t>();
          }

          if (jsonRoot["attributes"].contains("recoveryLevel")
              && !jsonRoot["attributes"]["recoveryLevel"].is_null())
          {
            response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel(
                jsonRoot["attributes"]["recoveryLevel"].get<std::string>());
          }
        }

        if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null())
        {
          response.Tags = std::map<std::string, std::string>{};

          for (auto const& kv : jsonRoot["tags"].items())
          {
            std::string value{};
            value = kv.value().get<std::string>();
            response.Tags.Value().emplace(kv.key(), value);
          }
        }

        if (jsonRoot.contains("preserveCertOrder") && !jsonRoot["preserveCertOrder"].is_null())
        {
          response.PreserveCertOrder = jsonRoot["preserveCertOrder"].get<bool>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::CertificateBundle>(std::move(response), std::move(rawResponse));
}
