// 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::Keys::_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-keys",
      _detail::PackageVersion::ToString(),
      std::move(perRetryPolicies),
      std::move(perCallPolicies));
}
// codegen: end replace KeyVaultClient::KeyVaultClient

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyBundle>
KeyVaultClient::CreateKey(
    const std::string& keyName,
    const Models::KeyCreateParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  url.AppendPath("create");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["kty"] = parameters.Kty.ToString();
    if (parameters.KeySize.HasValue())
    {
      jsonRoot["key_size"] = parameters.KeySize.Value();
    }

    if (parameters.PublicExponent.HasValue())
    {
      jsonRoot["public_exponent"] = parameters.PublicExponent.Value();
    }

    if (parameters.KeyOps.HasValue())
    {
      jsonRoot["key_ops"] = Core::Json::_internal::json::array();

      const size_t size = parameters.KeyOps.Value().size();
      for (size_t i = 0; i < size; ++i)
      {
        jsonRoot["key_ops"][i] = parameters.KeyOps.Value()[i].ToString();
      }
    }

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

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

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

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

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

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

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

      if (parameters.KeyAttributes.Value().Exportable.HasValue())
      {
        jsonRoot["attributes"]["exportable"] = parameters.KeyAttributes.Value().Exportable.Value();
      }

      if (parameters.KeyAttributes.Value().HsmPlatform.HasValue())
      {
        jsonRoot["attributes"]["hsmPlatform"]
            = parameters.KeyAttributes.Value().HsmPlatform.Value();
      }

      if (parameters.KeyAttributes.Value().Attestation.HasValue())
      {
        if (parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["certificatePemFile"]
              = Core::_internal::Base64Url::Base64UrlEncode(
                  parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().PrivateKeyAttestation.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
              = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value()
                                                                .Attestation.Value()
                                                                .PrivateKeyAttestation.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().PublicKeyAttestation.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
              = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value()
                                                                .Attestation.Value()
                                                                .PublicKeyAttestation.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().Version.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["version"]
              = parameters.KeyAttributes.Value().Attestation.Value().Version.Value();
        }
      }
    }

    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.Curve.HasValue())
    {
      jsonRoot["crv"] = parameters.Curve.Value().ToString();
    }

    if (parameters.ReleasePolicy.HasValue())
    {
      if (parameters.ReleasePolicy.Value().ContentType.HasValue())
      {
        jsonRoot["release_policy"]["contentType"]
            = parameters.ReleasePolicy.Value().ContentType.Value();
      }

      if (parameters.ReleasePolicy.Value().Immutable.HasValue())
      {
        jsonRoot["release_policy"]["immutable"]
            = parameters.ReleasePolicy.Value().Immutable.Value();
      }

      if (parameters.ReleasePolicy.Value().EncodedPolicy.HasValue())
      {
        jsonRoot["release_policy"]["data"] = Core::_internal::Base64Url::Base64UrlEncode(
            parameters.ReleasePolicy.Value().EncodedPolicy.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::KeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyBundle>
KeyVaultClient::RotateKey(const std::string& keyName, const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  url.AppendPath("rotate");

  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::KeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyBundle>
KeyVaultClient::ImportKey(
    const std::string& keyName,
    const Models::KeyImportParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));

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

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

    if (parameters.Key.Kid.HasValue())
    {
      jsonRoot["key"]["kid"] = parameters.Key.Kid.Value();
    }

    if (parameters.Key.Kty.HasValue())
    {
      jsonRoot["key"]["kty"] = parameters.Key.Kty.Value().ToString();
    }

    if (parameters.Key.KeyOps.HasValue())
    {
      jsonRoot["key"]["key_ops"] = Core::Json::_internal::json::array();

      const size_t size = parameters.Key.KeyOps.Value().size();
      for (size_t i = 0; i < size; ++i)
      {
        jsonRoot["key"]["key_ops"][i] = parameters.Key.KeyOps.Value()[i];
      }
    }

    if (parameters.Key.N.HasValue())
    {
      jsonRoot["key"]["n"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.N.Value());
    }

    if (parameters.Key.E.HasValue())
    {
      jsonRoot["key"]["e"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.E.Value());
    }

    if (parameters.Key.D.HasValue())
    {
      jsonRoot["key"]["d"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.D.Value());
    }

    if (parameters.Key.Dp.HasValue())
    {
      jsonRoot["key"]["dp"]
          = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Dp.Value());
    }

    if (parameters.Key.Dq.HasValue())
    {
      jsonRoot["key"]["dq"]
          = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Dq.Value());
    }

    if (parameters.Key.Qi.HasValue())
    {
      jsonRoot["key"]["qi"]
          = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Qi.Value());
    }

    if (parameters.Key.P.HasValue())
    {
      jsonRoot["key"]["p"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.P.Value());
    }

    if (parameters.Key.Q.HasValue())
    {
      jsonRoot["key"]["q"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Q.Value());
    }

    if (parameters.Key.K.HasValue())
    {
      jsonRoot["key"]["k"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.K.Value());
    }

    if (parameters.Key.T.HasValue())
    {
      jsonRoot["key"]["key_hsm"]
          = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.T.Value());
    }

    if (parameters.Key.Crv.HasValue())
    {
      jsonRoot["key"]["crv"] = parameters.Key.Crv.Value().ToString();
    }

    if (parameters.Key.X.HasValue())
    {
      jsonRoot["key"]["x"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.X.Value());
    }

    if (parameters.Key.Y.HasValue())
    {
      jsonRoot["key"]["y"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Y.Value());
    }

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

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

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

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

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

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

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

      if (parameters.KeyAttributes.Value().Exportable.HasValue())
      {
        jsonRoot["attributes"]["exportable"] = parameters.KeyAttributes.Value().Exportable.Value();
      }

      if (parameters.KeyAttributes.Value().HsmPlatform.HasValue())
      {
        jsonRoot["attributes"]["hsmPlatform"]
            = parameters.KeyAttributes.Value().HsmPlatform.Value();
      }

      if (parameters.KeyAttributes.Value().Attestation.HasValue())
      {
        if (parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["certificatePemFile"]
              = Core::_internal::Base64Url::Base64UrlEncode(
                  parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().PrivateKeyAttestation.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
              = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value()
                                                                .Attestation.Value()
                                                                .PrivateKeyAttestation.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().PublicKeyAttestation.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
              = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value()
                                                                .Attestation.Value()
                                                                .PublicKeyAttestation.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().Version.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["version"]
              = parameters.KeyAttributes.Value().Attestation.Value().Version.Value();
        }
      }
    }

    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.ReleasePolicy.HasValue())
    {
      if (parameters.ReleasePolicy.Value().ContentType.HasValue())
      {
        jsonRoot["release_policy"]["contentType"]
            = parameters.ReleasePolicy.Value().ContentType.Value();
      }

      if (parameters.ReleasePolicy.Value().Immutable.HasValue())
      {
        jsonRoot["release_policy"]["immutable"]
            = parameters.ReleasePolicy.Value().Immutable.Value();
      }

      if (parameters.ReleasePolicy.Value().EncodedPolicy.HasValue())
      {
        jsonRoot["release_policy"]["data"] = Core::_internal::Base64Url::Base64UrlEncode(
            parameters.ReleasePolicy.Value().EncodedPolicy.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::KeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

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

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

  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::DeletedKeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }

        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::DeletedKeyBundle>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyBundle>
KeyVaultClient::UpdateKey(
    const std::string& keyName,
    const std::string& keyVersion,
    const Models::KeyUpdateParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    if (parameters.KeyOps.HasValue())
    {
      jsonRoot["key_ops"] = Core::Json::_internal::json::array();

      const size_t size = parameters.KeyOps.Value().size();
      for (size_t i = 0; i < size; ++i)
      {
        jsonRoot["key_ops"][i] = parameters.KeyOps.Value()[i].ToString();
      }
    }

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

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

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

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

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

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

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

      if (parameters.KeyAttributes.Value().Exportable.HasValue())
      {
        jsonRoot["attributes"]["exportable"] = parameters.KeyAttributes.Value().Exportable.Value();
      }

      if (parameters.KeyAttributes.Value().HsmPlatform.HasValue())
      {
        jsonRoot["attributes"]["hsmPlatform"]
            = parameters.KeyAttributes.Value().HsmPlatform.Value();
      }

      if (parameters.KeyAttributes.Value().Attestation.HasValue())
      {
        if (parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["certificatePemFile"]
              = Core::_internal::Base64Url::Base64UrlEncode(
                  parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().PrivateKeyAttestation.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
              = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value()
                                                                .Attestation.Value()
                                                                .PrivateKeyAttestation.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().PublicKeyAttestation.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
              = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value()
                                                                .Attestation.Value()
                                                                .PublicKeyAttestation.Value());
        }

        if (parameters.KeyAttributes.Value().Attestation.Value().Version.HasValue())
        {
          jsonRoot["attributes"]["attestation"]["version"]
              = parameters.KeyAttributes.Value().Attestation.Value().Version.Value();
        }
      }
    }

    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.ReleasePolicy.HasValue())
    {
      if (parameters.ReleasePolicy.Value().ContentType.HasValue())
      {
        jsonRoot["release_policy"]["contentType"]
            = parameters.ReleasePolicy.Value().ContentType.Value();
      }

      if (parameters.ReleasePolicy.Value().Immutable.HasValue())
      {
        jsonRoot["release_policy"]["immutable"]
            = parameters.ReleasePolicy.Value().Immutable.Value();
      }

      if (parameters.ReleasePolicy.Value().EncodedPolicy.HasValue())
      {
        jsonRoot["release_policy"]["data"] = Core::_internal::Base64Url::Base64UrlEncode(
            parameters.ReleasePolicy.Value().EncodedPolicy.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::KeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::KeyBundle>(std::move(response), std::move(rawResponse));
}
// codegen: replace KeyVaultClient::GetKey
Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyBundle> KeyVaultClient::GetKey(
    const std::string& keyName,
    const std::string& keyVersion,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (!keyVersion.empty())
  {
    url.AppendPath(Core::Url::Encode(keyVersion));
  }
  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::KeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

  return Response<Models::KeyBundle>(std::move(response), std::move(rawResponse));
}
// codegen: end replace KeyVaultClient::GetKey
GetKeyVersionsPagedResponse KeyVaultClient::GetKeyVersions(
    const std::string& keyName,
    const KeyVaultClientGetKeyVersionsOptions& options,
    const Core::Context& context) const
{
  Core::Url url;
  if (options.NextPageToken.empty())
  {
    url = m_url;
    url.AppendPath("keys/");
    if (keyName.empty())
    {
      throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
    }
    url.AppendPath(Core::Url::Encode(keyName));
    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);
  }

  GetKeyVersionsPagedResponse response{};
  response.m_client = std::make_shared<KeyVaultClient>(*this);
  response.m_keyName = keyName;
  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::KeyItem>{};

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

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

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

              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["attributes"].contains("exportable")
                  && !jsonItem["attributes"]["exportable"].is_null())
              {
                vectorItem.Attributes.Value().Exportable
                    = jsonItem["attributes"]["exportable"].get<bool>();
              }

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

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

                if (jsonItem["attributes"]["attestation"].contains("certificatePemFile")
                    && !jsonItem["attributes"]["attestation"]["certificatePemFile"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().CertificatePemFile
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["certificatePemFile"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("privateKeyAttestation")
                    && !jsonItem["attributes"]["attestation"]["privateKeyAttestation"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["privateKeyAttestation"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("publicKeyAttestation")
                    && !jsonItem["attributes"]["attestation"]["publicKeyAttestation"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().PublicKeyAttestation
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["publicKeyAttestation"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("version")
                    && !jsonItem["attributes"]["attestation"]["version"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().Version
                      = jsonItem["attributes"]["attestation"]["version"].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("managed") && !jsonItem["managed"].is_null())
            {
              vectorItem.Managed = jsonItem["managed"].get<bool>();
            }

            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;
}

GetKeysPagedResponse KeyVaultClient::GetKeys(
    const KeyVaultClientGetKeysOptions& options,
    const Core::Context& context) const
{
  Core::Url url;
  if (options.NextPageToken.empty())
  {
    url = m_url;
    url.AppendPath("keys");

    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);
  }

  GetKeysPagedResponse 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::KeyItem>{};

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

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

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

              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["attributes"].contains("exportable")
                  && !jsonItem["attributes"]["exportable"].is_null())
              {
                vectorItem.Attributes.Value().Exportable
                    = jsonItem["attributes"]["exportable"].get<bool>();
              }

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

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

                if (jsonItem["attributes"]["attestation"].contains("certificatePemFile")
                    && !jsonItem["attributes"]["attestation"]["certificatePemFile"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().CertificatePemFile
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["certificatePemFile"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("privateKeyAttestation")
                    && !jsonItem["attributes"]["attestation"]["privateKeyAttestation"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["privateKeyAttestation"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("publicKeyAttestation")
                    && !jsonItem["attributes"]["attestation"]["publicKeyAttestation"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().PublicKeyAttestation
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["publicKeyAttestation"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("version")
                    && !jsonItem["attributes"]["attestation"]["version"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().Version
                      = jsonItem["attributes"]["attestation"]["version"].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("managed") && !jsonItem["managed"].is_null())
            {
              vectorItem.Managed = jsonItem["managed"].get<bool>();
            }

            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::Keys::_detail::Models::BackupKeyResult>
KeyVaultClient::BackupKey(const std::string& keyName, const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  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::BackupKeyResult 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::BackupKeyResult>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyBundle> KeyVaultClient::
    RestoreKey(const Models::KeyRestoreParameters& parameters, const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/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.KeyBundleBackup);
    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::KeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyOperationResult>
KeyVaultClient::Encrypt(
    const std::string& keyName,
    const std::string& keyVersion,
    const Models::KeyOperationsParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));
  url.AppendPath("encrypt");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["alg"] = parameters.Algorithm.ToString();
    jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value);
    if (parameters.Iv.HasValue())
    {
      jsonRoot["iv"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Iv.Value());
    }

    if (parameters.Aad.HasValue())
    {
      jsonRoot["aad"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Aad.Value());
    }

    if (parameters.Tag.HasValue())
    {
      jsonRoot["tag"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Tag.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::KeyOperationResult 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("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

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

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

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

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

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyOperationResult>
KeyVaultClient::Decrypt(
    const std::string& keyName,
    const std::string& keyVersion,
    const Models::KeyOperationsParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));
  url.AppendPath("decrypt");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["alg"] = parameters.Algorithm.ToString();
    jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value);
    if (parameters.Iv.HasValue())
    {
      jsonRoot["iv"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Iv.Value());
    }

    if (parameters.Aad.HasValue())
    {
      jsonRoot["aad"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Aad.Value());
    }

    if (parameters.Tag.HasValue())
    {
      jsonRoot["tag"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Tag.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::KeyOperationResult 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("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

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

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

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

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

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyOperationResult>
KeyVaultClient::Sign(
    const std::string& keyName,
    const std::string& keyVersion,
    const Models::KeySignParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));
  url.AppendPath("sign");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["alg"] = parameters.Algorithm.ToString();
    jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.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::KeyOperationResult 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("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

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

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

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

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

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyVerifyResult>
KeyVaultClient::Verify(
    const std::string& keyName,
    const std::string& keyVersion,
    const Models::KeyVerifyParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));
  url.AppendPath("verify");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["alg"] = parameters.Algorithm.ToString();
    jsonRoot["digest"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Digest);
    jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Signature);
    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::KeyVerifyResult 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 = jsonRoot["value"].get<bool>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyOperationResult>
KeyVaultClient::WrapKey(
    const std::string& keyName,
    const std::string& keyVersion,
    const Models::KeyOperationsParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));
  url.AppendPath("wrapkey");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["alg"] = parameters.Algorithm.ToString();
    jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value);
    if (parameters.Iv.HasValue())
    {
      jsonRoot["iv"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Iv.Value());
    }

    if (parameters.Aad.HasValue())
    {
      jsonRoot["aad"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Aad.Value());
    }

    if (parameters.Tag.HasValue())
    {
      jsonRoot["tag"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Tag.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::KeyOperationResult 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("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

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

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

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

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

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyOperationResult>
KeyVaultClient::UnwrapKey(
    const std::string& keyName,
    const std::string& keyVersion,
    const Models::KeyOperationsParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));
  url.AppendPath("unwrapkey");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["alg"] = parameters.Algorithm.ToString();
    jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value);
    if (parameters.Iv.HasValue())
    {
      jsonRoot["iv"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Iv.Value());
    }

    if (parameters.Aad.HasValue())
    {
      jsonRoot["aad"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Aad.Value());
    }

    if (parameters.Tag.HasValue())
    {
      jsonRoot["tag"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Tag.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::KeyOperationResult 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("kid") && !jsonRoot["kid"].is_null())
        {
          response.Kid = jsonRoot["kid"].get<std::string>();
        }

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

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

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

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

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyReleaseResult>
KeyVaultClient::Release(
    const std::string& keyName,
    const std::string& keyVersion,
    const Models::KeyReleaseParameters& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));
  url.AppendPath("release");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["target"] = parameters.TargetAttestationToken;
    if (parameters.Nonce.HasValue())
    {
      jsonRoot["nonce"] = parameters.Nonce.Value();
    }

    if (parameters.Enc.HasValue())
    {
      jsonRoot["enc"] = parameters.Enc.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::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::KeyReleaseResult 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 = jsonRoot["value"].get<std::string>();
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

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

GetDeletedKeysPagedResponse KeyVaultClient::GetDeletedKeys(
    const KeyVaultClientGetDeletedKeysOptions& options,
    const Core::Context& context) const
{
  Core::Url url;
  if (options.NextPageToken.empty())
  {
    url = m_url;
    url.AppendPath("deletedkeys");

    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);
  }

  GetDeletedKeysPagedResponse 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::DeletedKeyItem>{};

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

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

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

              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["attributes"].contains("exportable")
                  && !jsonItem["attributes"]["exportable"].is_null())
              {
                vectorItem.Attributes.Value().Exportable
                    = jsonItem["attributes"]["exportable"].get<bool>();
              }

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

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

                if (jsonItem["attributes"]["attestation"].contains("certificatePemFile")
                    && !jsonItem["attributes"]["attestation"]["certificatePemFile"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().CertificatePemFile
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["certificatePemFile"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("privateKeyAttestation")
                    && !jsonItem["attributes"]["attestation"]["privateKeyAttestation"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["privateKeyAttestation"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("publicKeyAttestation")
                    && !jsonItem["attributes"]["attestation"]["publicKeyAttestation"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().PublicKeyAttestation
                      = Core::_internal::Base64Url::Base64UrlDecode(
                          jsonItem["attributes"]["attestation"]["publicKeyAttestation"]
                              .get<std::string>());
                }

                if (jsonItem["attributes"]["attestation"].contains("version")
                    && !jsonItem["attributes"]["attestation"]["version"].is_null())
                {
                  vectorItem.Attributes.Value().Attestation.Value().Version
                      = jsonItem["attributes"]["attestation"]["version"].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("managed") && !jsonItem["managed"].is_null())
            {
              vectorItem.Managed = jsonItem["managed"].get<bool>();
            }

            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::Keys::_detail::Models::DeletedKeyBundle>
KeyVaultClient::GetDeletedKey(const std::string& keyName, const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("deletedkeys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));

  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::DeletedKeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }

        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::DeletedKeyBundle>(std::move(response), std::move(rawResponse));
}

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

  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::PurgeDeletedKeyResult response{};

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyBundle>
KeyVaultClient::RecoverDeletedKey(const std::string& keyName, const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("deletedkeys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  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::KeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

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

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyRotationPolicy>
KeyVaultClient::GetKeyRotationPolicy(const std::string& keyName, const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  url.AppendPath("rotationpolicy");

  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::KeyRotationPolicy 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("lifetimeActions") && !jsonRoot["lifetimeActions"].is_null())
        {
          response.LifetimeActions = std::vector<Models::LifetimeActions>{};

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

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

              if (jsonItem["trigger"].contains("timeAfterCreate")
                  && !jsonItem["trigger"]["timeAfterCreate"].is_null())
              {
                vectorItem.Trigger.Value().TimeAfterCreate
                    = jsonItem["trigger"]["timeAfterCreate"].get<std::string>();
              }

              if (jsonItem["trigger"].contains("timeBeforeExpiry")
                  && !jsonItem["trigger"]["timeBeforeExpiry"].is_null())
              {
                vectorItem.Trigger.Value().TimeBeforeExpiry
                    = jsonItem["trigger"]["timeBeforeExpiry"].get<std::string>();
              }
            }

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

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

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

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

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

          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::KeyRotationPolicy>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyRotationPolicy>
KeyVaultClient::UpdateKeyRotationPolicy(
    const std::string& keyName,
    const Models::KeyRotationPolicy& keyRotationPolicy,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  url.AppendPath("rotationpolicy");

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

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

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

      const size_t size = keyRotationPolicy.LifetimeActions.Value().size();
      for (size_t i = 0; i < size; ++i)
      {
        if (keyRotationPolicy.LifetimeActions.Value()[i].Trigger.HasValue())
        {
          if (keyRotationPolicy.LifetimeActions.Value()[i]
                  .Trigger.Value()
                  .TimeAfterCreate.HasValue())
          {
            jsonRoot["lifetimeActions"][i]["trigger"]["timeAfterCreate"]
                = keyRotationPolicy.LifetimeActions.Value()[i]
                      .Trigger.Value()
                      .TimeAfterCreate.Value();
          }

          if (keyRotationPolicy.LifetimeActions.Value()[i]
                  .Trigger.Value()
                  .TimeBeforeExpiry.HasValue())
          {
            jsonRoot["lifetimeActions"][i]["trigger"]["timeBeforeExpiry"]
                = keyRotationPolicy.LifetimeActions.Value()[i]
                      .Trigger.Value()
                      .TimeBeforeExpiry.Value();
          }
        }

        if (keyRotationPolicy.LifetimeActions.Value()[i].Action.HasValue())
        {
          if (keyRotationPolicy.LifetimeActions.Value()[i].Action.Value().Type.HasValue())
          {
            jsonRoot["lifetimeActions"][i]["action"]["type"]
                = keyRotationPolicy.LifetimeActions.Value()[i]
                      .Action.Value()
                      .Type.Value()
                      .ToString();
          }
        }
      }
    }

    if (keyRotationPolicy.Attributes.HasValue())
    {
      if (keyRotationPolicy.Attributes.Value().ExpiryTime.HasValue())
      {
        jsonRoot["attributes"]["expiryTime"]
            = keyRotationPolicy.Attributes.Value().ExpiryTime.Value();
      }

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

      if (keyRotationPolicy.Attributes.Value().Updated.HasValue())
      {
        jsonRoot["attributes"]["updated"]
            = Core::_internal::PosixTimeConverter::DateTimeToPosixTime(
                keyRotationPolicy.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::KeyRotationPolicy 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("lifetimeActions") && !jsonRoot["lifetimeActions"].is_null())
        {
          response.LifetimeActions = std::vector<Models::LifetimeActions>{};

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

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

              if (jsonItem["trigger"].contains("timeAfterCreate")
                  && !jsonItem["trigger"]["timeAfterCreate"].is_null())
              {
                vectorItem.Trigger.Value().TimeAfterCreate
                    = jsonItem["trigger"]["timeAfterCreate"].get<std::string>();
              }

              if (jsonItem["trigger"].contains("timeBeforeExpiry")
                  && !jsonItem["trigger"]["timeBeforeExpiry"].is_null())
              {
                vectorItem.Trigger.Value().TimeBeforeExpiry
                    = jsonItem["trigger"]["timeBeforeExpiry"].get<std::string>();
              }
            }

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

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

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

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

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

          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::KeyRotationPolicy>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::RandomBytes>
KeyVaultClient::GetRandomBytes(
    const Models::GetRandomBytesRequest& parameters,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("rng");

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

  std::string jsonBody;
  {
    auto jsonRoot = Core::Json::_internal::json::object();
    jsonRoot["count"] = parameters.Count;
    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::RandomBytes response{};
  {
    const auto& responseBody = rawResponse->GetBody();
    if (responseBody.size() > 0)
    {
      try
      {
        const auto jsonRoot
            = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end());

        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::RandomBytes>(std::move(response), std::move(rawResponse));
}

Azure::Response<Azure::Security::KeyVault::Keys::_detail::Models::KeyBundle>
KeyVaultClient::GetKeyAttestation(
    const std::string& keyName,
    const std::string& keyVersion,
    const Core::Context& context) const
{
  auto url = m_url;
  url.AppendPath("keys/");
  if (keyName.empty())
  {
    throw std::invalid_argument("Parameter 'keyName' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyName));
  if (keyVersion.empty())
  {
    throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string.");
  }
  url.AppendPath(Core::Url::Encode(keyVersion));
  url.AppendPath("attestation");

  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::KeyBundle 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("key") && !jsonRoot["key"].is_null())
        {
          response.Key = Models::JsonWebKey{};

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

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

          if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null())
          {
            response.Key.Value().KeyOps = std::vector<std::string>{};

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

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

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

          if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null())
          {
            response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["n"].get<std::string>());
          }

          if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null())
          {
            response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["e"].get<std::string>());
          }

          if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null())
          {
            response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["d"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null())
          {
            response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dp"].get<std::string>());
          }

          if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null())
          {
            response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["dq"].get<std::string>());
          }

          if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null())
          {
            response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["qi"].get<std::string>());
          }

          if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null())
          {
            response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["p"].get<std::string>());
          }

          if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null())
          {
            response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["q"].get<std::string>());
          }

          if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null())
          {
            response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["k"].get<std::string>());
          }

          if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null())
          {
            response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["key_hsm"].get<std::string>());
          }

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

          if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null())
          {
            response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["x"].get<std::string>());
          }

          if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null())
          {
            response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode(
                jsonRoot["key"]["y"].get<std::string>());
          }
        }

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

          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["attributes"].contains("exportable")
              && !jsonRoot["attributes"]["exportable"].is_null())
          {
            response.Attributes.Value().Exportable
                = jsonRoot["attributes"]["exportable"].get<bool>();
          }

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

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

            if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile")
                && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null())
            {
              response.Attributes.Value().Attestation.Value().CertificatePemFile
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["certificatePemFile"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PrivateKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["privateKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation")
                && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null())
            {
              response.Attributes.Value().Attestation.Value().PublicKeyAttestation
                  = Core::_internal::Base64Url::Base64UrlDecode(
                      jsonRoot["attributes"]["attestation"]["publicKeyAttestation"]
                          .get<std::string>());
            }

            if (jsonRoot["attributes"]["attestation"].contains("version")
                && !jsonRoot["attributes"]["attestation"]["version"].is_null())
            {
              response.Attributes.Value().Attestation.Value().Version
                  = jsonRoot["attributes"]["attestation"]["version"].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("managed") && !jsonRoot["managed"].is_null())
        {
          response.Managed = jsonRoot["managed"].get<bool>();
        }

        if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null())
        {
          response.ReleasePolicy = Models::KeyReleasePolicy{};

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

          if (jsonRoot["release_policy"].contains("immutable")
              && !jsonRoot["release_policy"]["immutable"].is_null())
          {
            response.ReleasePolicy.Value().Immutable
                = jsonRoot["release_policy"]["immutable"].get<bool>();
          }

          if (jsonRoot["release_policy"].contains("data")
              && !jsonRoot["release_policy"]["data"].is_null())
          {
            response.ReleasePolicy.Value().EncodedPolicy
                = Core::_internal::Base64Url::Base64UrlDecode(
                    jsonRoot["release_policy"]["data"].get<std::string>());
          }
        }
      }
      catch (Core::Json::_internal::json::exception const& ex)
      {
        throw Core::RequestFailedException(ex.what());
      }
    }
  }

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