diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp
index 42a08d9392f651f0676320685ffc6b06ca104dd8..b3c1ca3d02db51e160c95c9a6c9e032fab8f66af 100644
--- a/indra/llcommon/llsdjson.cpp
+++ b/indra/llcommon/llsdjson.cpp
@@ -33,44 +33,45 @@
 
 #include "llerror.h"
 
+#include <boost/json/src.hpp>
 
 //=========================================================================
-LLSD LlsdFromJson(const nlohmann::json &val)
+LLSD LlsdFromJson(const boost::json::value& val)
 {
     LLSD result;
 
-    switch (val.type())
+    switch (val.kind())
     {
     default:
-    case nlohmann::json::value_t::null:
+    case boost::json::kind::null:
         break;
-    case nlohmann::json::value_t::number_integer:
-        result = LLSD(val.get<LLSD::Integer>());
+    case boost::json::kind::int64:
+        result = LLSD(val.as_int64());
         break;
-    case nlohmann::json::value_t::number_unsigned:
-        result = LLSD(val.get<LLSD::Integer>());
+    case boost::json::kind::uint64:
+        result = LLSD(val.as_uint64());
         break;
-    case nlohmann::json::value_t::number_float:
-        result = LLSD(val.get<LLSD::Real>());
+    case boost::json::kind::double_:
+        result = LLSD(val.as_double());
         break;
-    case nlohmann::json::value_t::string:
-        result = LLSD(val.get<LLSD::String>());
+    case boost::json::kind::string:
+        result = LLSD(std::string(val.as_string()));
         break;
-    case nlohmann::json::value_t::boolean:
-        result = LLSD(val.get<LLSD::Boolean>());
+    case boost::json::kind::bool_:
+        result = LLSD(val.as_bool());
         break;
-    case nlohmann::json::value_t::array:
+    case boost::json::kind::array:
         result = LLSD::emptyArray();
-        for (const auto &element : val)
+        for (const auto &element : val.as_array())
         {
             result.append(LlsdFromJson(element));
         }
         break;
-    case nlohmann::json::value_t::object:
+    case boost::json::kind::object:
         result = LLSD::emptyMap();
-        for (auto it = val.cbegin(), end = val.cend(); it != end; ++it)
+        for (const auto& element : val.as_object())
         {
-            result[it.key()] = LlsdFromJson(it.value());
+            result[element.key()] = LlsdFromJson(element.value());
         }
         break;
     }
@@ -78,9 +79,9 @@ LLSD LlsdFromJson(const nlohmann::json &val)
 }
 
 //=========================================================================
-nlohmann::json LlsdToJson(const LLSD &val)
+boost::json::value LlsdToJson(const LLSD &val)
 {
-    nlohmann::json result;
+    boost::json::value result;
 
     switch (val.type())
     {
@@ -103,17 +104,23 @@ nlohmann::json LlsdToJson(const LLSD &val)
         result = val.asString();
         break;
     case LLSD::TypeMap:
-        for (auto it = val.beginMap(), it_end = val.endMap(); it != it_end; ++it)
+    {
+        boost::json::object& obj = result.emplace_object();
+        for (const auto& llsd_dat : val.asMap())
         {
-            result[it->first] = LlsdToJson(it->second);
+            obj[llsd_dat.first] = LlsdToJson(llsd_dat.second);
         }
         break;
+    }
     case LLSD::TypeArray:
-        for (auto it = val.beginArray(), end = val.endArray(); it != end; ++it)
+    {
+        boost::json::array& json_array = result.emplace_array();
+        for (const auto& llsd_dat : val.asArray())
         {
-            result.push_back(LlsdToJson(*it));
+            json_array.push_back(LlsdToJson(llsd_dat));
         }
         break;
+    }
     case LLSD::TypeBinary:
     default:
         LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" << val.type() << ")." << LL_ENDL;
diff --git a/indra/llcommon/llsdjson.h b/indra/llcommon/llsdjson.h
index 19f4883053c488e591b259ebce944a8e0734f51d..140cc53748f3e3c42d8a812130fdb0a3fdf0d979 100644
--- a/indra/llcommon/llsdjson.h
+++ b/indra/llcommon/llsdjson.h
@@ -30,7 +30,7 @@
 
 
 #include "llsd.h"
-#include <nlohmann/json.hpp>
+#include <boost/json.hpp>
 
 /// Convert a parsed JSON structure into LLSD maintaining member names and 
 /// array indexes.
@@ -49,7 +49,7 @@
 ///  
 /// For maps and arrays child entries will be converted and added to the structure.
 /// Order is preserved for an array but not for objects.
-LLSD LlsdFromJson(const nlohmann::json &val);
+LLSD LlsdFromJson(const boost::json::value &val);
 
 /// Convert an LLSD object into Parsed JSON object maintaining member names and 
 /// array indexs.
@@ -68,6 +68,6 @@ LLSD LlsdFromJson(const nlohmann::json &val);
 /// TypeMap       | object
 /// TypeArray     | array
 /// TypeBinary    | unsupported 
-nlohmann::json LlsdToJson(const LLSD &val);
+boost::json::value LlsdToJson(const LLSD &val);
 
 #endif // LL_LLSDJSON_H
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index 8fc1906d8ddbdab03684ce230643c9b11ad9d170..c2fa12543910078d6b37f5f17df5d867c229125d 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -30,7 +30,6 @@
 #include <sstream>
 #include <algorithm>
 #include <iterator>
-#include <nlohmann/json.hpp> // JSON
 #include <utility>
 #include "llcorehttputil.h"
 #include "llhttpconstants.h"
@@ -585,20 +584,12 @@ LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:
     }
 
     LLCore::BufferArrayStream bas(body);
-    nlohmann::json jsonRoot;
 
-    try
-    {
-        bas >> jsonRoot;
-    }
-    catch (const nlohmann::json::exception& e)
-    {   // deserialization failed.  Record the reason and pass back an empty map for markup.
-        status = LLCore::HttpStatus(499, std::string(e.what()));
-        return result;
-    }
-    catch (const std::runtime_error& e)
+    boost::json::error_code ec;
+    boost::json::value jsonRoot = boost::json::parse(bas, ec);
+    if(ec.failed())
     {   // deserialization failed.  Record the reason and pass back an empty map for markup.
-        status = LLCore::HttpStatus(499, std::string(e.what()));
+        status = LLCore::HttpStatus(499, std::string(ec.what()));
         return result;
     }
 
@@ -618,19 +609,11 @@ LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse *response, bool &succes
     }
 
     LLCore::BufferArrayStream bas(body);
-    nlohmann::json jsonRoot;
 
-    try
+    boost::json::error_code ec;
+    boost::json::value jsonRoot = boost::json::parse(bas, ec);
+    if (ec.failed())
     {
-        bas >> jsonRoot;
-    }
-    catch (const nlohmann::json::exception&)
-    {
-        success = false;
-        return LLSD();
-    }
-    catch (const std::runtime_error&)
-    {   
         success = false;
         return LLSD();
     }
@@ -812,8 +795,8 @@ LLSD HttpCoroutineAdapter::postJsonAndSuspend(LLCore::HttpRequest::ptr_t request
 
     {
         LLCore::BufferArrayStream outs(rawbody.get());
-        nlohmann::json root = LlsdToJson(body);
-        std::string value = root.dump();
+        auto root = LlsdToJson(body);
+        std::string value = boost::json::serialize(root);
 
         LL_WARNS("Http::post") << "JSON Generates: \"" << value << "\"" << LL_ENDL;
 
@@ -871,8 +854,8 @@ LLSD HttpCoroutineAdapter::putJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
 
     {
         LLCore::BufferArrayStream outs(rawbody.get());
-        nlohmann::json root = LlsdToJson(body);
-        std::string value = root.dump();
+        auto root = LlsdToJson(body);
+        std::string value = boost::json::serialize(root);
 
         LL_WARNS("Http::put") << "JSON Generates: \"" << value << "\"" << LL_ENDL;
         outs << value;
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index c1d65363307405a8d8c55200e8aeb23ad91158a2..1eabc917d7cf2de0209b0bb14905a451820bc675 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -123,7 +123,7 @@
 #include "llviewercontrol.h"
 #include "llpresetsmanager.h"
 
-#include <nlohmann/json.hpp>
+#include <boost/json.hpp>
 #include <utility>
 
 #include "llsearchableui.h"
@@ -668,29 +668,30 @@ bool LLFloaterPreference::handleRemoveGridCB(const LLSD& notification, const LLS
 skin_t manifestFromJson(const std::string& filename, const ESkinType type)
 {
 	skin_t skin;
-	nlohmann::json root;
 	llifstream in;
 	in.open(filename);
 	if (in.is_open())
 	{
-        try
+		boost::json::error_code ec;
+		auto root = boost::json::parse(in, ec);
+		if (!ec.failed() && root.is_object())
         {
-            in >> root;
-            skin.mName = root.value("name", "Unknown");
-            skin.mAuthor = root.value("author", "Unknown");
-            skin.mUrl = root.value("url", "Unknown");
-			skin.mCompatVer = root.value("compatibility", "Unknown");
-			skin.mDate = LLDate(root.value("date", LLDate::now().asString()));
-			skin.mNotes = root.value("notes", "");
+			auto jobj = root.as_object();
+            skin.mName = jobj.contains("name") ? boost::json::value_to<std::string>(jobj.at("name")) : "Unknown";
+            skin.mAuthor = jobj.contains("author") ? boost::json::value_to<std::string>(jobj.at("author")) : LLTrans::getString("Unknown");
+            skin.mUrl = jobj.contains("url") ? boost::json::value_to<std::string>(jobj.at("url")) : LLTrans::getString("Unknown");
+			skin.mCompatVer = jobj.contains("compatibility") ? boost::json::value_to<std::string>(jobj.at("compatibility")) : LLTrans::getString("Unknown");
+			skin.mDate = jobj.contains("date") ? LLDate(boost::json::value_to<std::string>(jobj.at("date"))) : LLDate::now();
+			skin.mNotes = jobj.contains("notes") ? boost::json::value_to<std::string>(jobj.at("notes")) : "";
 			// If it's a system skin, the compatability version is always the current build
 			if (type == SYSTEM_SKIN)
 			{
 				skin.mCompatVer = LLVersionInfo::instance().getShortVersion();
 			}
         } 
-		catch(const nlohmann::json::exception& e)
+		else
 		{
-			LL_WARNS() << "Failed to parse " << filename << ": " << e.what() << LL_ENDL;
+			LL_WARNS() << "Failed to parse " << filename << ": " << ec.message() << LL_ENDL;
 		}
 		in.close();
 	}
@@ -784,11 +785,12 @@ void LLFloaterPreference::onAddSkinCallback(const std::vector<std::string>& file
 			ss << std::string(const_cast<const char*>(buf.get()), buf_size);
 			buf.reset();
 				
-			nlohmann::json root;
-			try
+			boost::json::error_code ec;
+			auto root = boost::json::parse(ss, ec);
+			if (!ec.failed() && root.is_object())
 			{
-                ss >> root;
-				const std::string& name = root.value("name", "Unknown");
+				const auto& jobj = root.as_object();
+				const std::string& name = jobj.contains("name") ? boost::json::value_to<std::string>(jobj.at("name")) : "Unknown";
 				std::string pathname = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "skins");
 				if (!gDirUtilp->fileExists(pathname))
 				{
@@ -809,7 +811,7 @@ void LLFloaterPreference::onAddSkinCallback(const std::vector<std::string>& file
 					LLNotificationsUtil::add("AddSkinSuccess", LLSD().with("PACKAGE", name));
 				}
 			}
-            catch(const nlohmann::json::exception&)
+			else
 			{
 				LLNotificationsUtil::add("AddSkinCantParseManifest", LLSD().with("PACKAGE", package));
 			}
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index d090dce32b622e92e3eb2f9cacac133deee36801..7da4b0b165ce94b172fc99590117fde777fd3e07 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -40,7 +40,7 @@
 #include "llurlregistry.h"
 #include "stringize.h"
 
-#include <nlohmann/json.hpp>
+#include <boost/json.hpp>
 
 static const std::string AZURE_NOTRANSLATE_OPENING_TAG("<div translate=\"no\">");
 static const std::string AZURE_NOTRANSLATE_CLOSING_TAG("</div>");
@@ -346,11 +346,11 @@ class LLGoogleTranslationHandler : public LLTranslationAPIHandler
 
 private:
     static void parseErrorResponse(
-        const nlohmann::json &root,
+        const boost::json::value &root,
         int &status,
         std::string &err_msg);
     static bool parseTranslation(
-        const nlohmann::json &root,
+        const boost::json::value&root,
         std::string &translation,
         std::string &detected_lang);
     static std::string getAPIKey();
@@ -399,17 +399,13 @@ bool LLGoogleTranslationHandler::parseResponse(
 	std::string& detected_lang,
 	std::string& err_msg) const
 {
-	std::stringstream stream(body);
-	nlohmann::json root;
-    try
+    boost::json::error_code ec;
+    boost::json::value root = boost::json::parse(body, ec);
+    if (ec.failed())
     {
-		stream >> root;
+        err_msg = ec.what();
+        return false;
     }
-    catch(nlohmann::json::exception &e)
-	{
-		err_msg = e.what();
-		return false;
-	}
 
 	if (!root.is_object()) // empty response? should not happen
 	{
@@ -435,48 +431,49 @@ bool LLGoogleTranslationHandler::isConfigured() const
 
 // static
 void LLGoogleTranslationHandler::parseErrorResponse(
-	const nlohmann::json &root,
+	const boost::json::value &root,
 	int &status,
 	std::string &err_msg)
 {
-    const nlohmann::json &error = root.at("error");
-	if (!error.is_object() || error.find("message") == error.end() || error.find("code") == error.end())
+    boost::json::error_code ec;
+    const boost::json::value &error = root.at("error");
+	if (!error.is_object() || !error.as_object().contains("message") || !error.as_object().contains("code"))
 	{
 		return;
 	}
 
-	err_msg = error["message"].get<std::string>();
-	status = error.at("code");
+    err_msg = boost::json::value_to<std::string>(error.at("message"));
+	status = boost::json::value_to<int>(error.at("code"));
 }
 
 // static
 bool LLGoogleTranslationHandler::parseTranslation(
-	const nlohmann::json &root,
+	const boost::json::value &root,
 	std::string &translation,
 	std::string &detected_lang)
 {
 	// Json is prone to aborting the program on failed assertions,
 	// so be super-careful and verify the response format.
-	const nlohmann::json &data = root.at("data");
-	if (!data.is_object() || data.find("translations") == data.end())
+	const boost::json::value &data = root.at("data");
+	if (!data.is_object() || !data.as_object().contains("translations"))
 	{
 		return false;
 	}
 
-	const nlohmann::json &translations = data["translations"];
-	if (!translations.is_array() || translations.empty())
+	const boost::json::value&translations = data.at("translations");
+	if (!translations.is_array() || translations.as_array().empty())
 	{
 		return false;
 	}
 
-	const nlohmann::json &first = translations[0];
-	if (!first.is_object() || first.find("translatedText") == first.end())
+	const boost::json::value &first = translations.at(0);
+	if (!first.is_object() || !first.as_object().contains("translatedText"))
 	{
 		return false;
 	}
 
-	translation = first["translatedText"].get<std::string>();
-    detected_lang = first.value("detectedSourceLanguage", "");
+	translation = boost::json::value_to<std::string>(first.at("translatedText"));
+    detected_lang = first.as_object().contains("detectedSourceLanguage") ? boost::json::value_to<std::string>(first.at("detectedSourceLanguage")) : "";
 	return true;
 }
 
@@ -658,17 +655,13 @@ bool LLAzureTranslationHandler::checkVerificationResponse(
     // Expected: "{\"error\":{\"code\":400000,\"message\":\"One of the request inputs is not valid.\"}}"
     // But for now just verify response is a valid json
 
-	std::stringstream stream(response["error_body"].asString());
-	nlohmann::json root;
-    try
+    boost::json::error_code ec;
+    boost::json::value root = boost::json::parse(response["error_body"].asString(), ec);
+    if (ec.failed())
     {
-		stream >> root;
+        LL_DEBUGS("Translate") << "Failed to parse error_body:" << ec.what() << LL_ENDL;
+        return false;
     }
-    catch(nlohmann::json::exception &e)
-	{
-        LL_DEBUGS("Translate") << "Failed to parse error_body:" << e.what() << LL_ENDL;
-		return false;
-	}
 
     return true;
 }
@@ -692,16 +685,13 @@ bool LLAzureTranslationHandler::parseResponse(
     //Example:
     // "[{\"detectedLanguage\":{\"language\":\"en\",\"score\":1.0},\"translations\":[{\"text\":\"Hello, what is your name?\",\"to\":\"en\"}]}]"
 
-	nlohmann::json root;
-    try
+    boost::json::error_code ec;
+    boost::json::value root = boost::json::parse(body, ec);
+    if (ec.failed())
     {
-		root = nlohmann::json::parse(body);
-    }
-    catch(nlohmann::json::exception &e)
-	{
-        err_msg = e.what();
+        err_msg = ec.what();
         return false;
-	}
+    }
 
     if (!root.is_array()) // empty response? should not happen
     {
@@ -710,34 +700,34 @@ bool LLAzureTranslationHandler::parseResponse(
 
     // Request succeeded, extract translation from the response.
 
-    const nlohmann::json& data = root[0U];
+    const boost::json::value& data = root.at(0U);
     if (!data.is_object()
-        || data.find("detectedLanguage") == data.end()
-        || data.find("translations") == data.end())
+        || !data.as_object().contains("detectedLanguage")
+        || !data.as_object().contains("translations"))
     {
         return false;
     }
 
-    const nlohmann::json& detectedLanguage = data["detectedLanguage"];
-    if (!detectedLanguage.is_object() || detectedLanguage.find("language") == detectedLanguage.end())
+    const boost::json::value& detectedLanguage = data.at("detectedLanguage");
+    if (!detectedLanguage.is_object() || !detectedLanguage.as_object().contains("language"))
     {
         return false;
     }
-    detected_lang = detectedLanguage["language"].get<std::string>();
+    detected_lang = boost::json::value_to<std::string>(detectedLanguage.at("language"));
 
-    const nlohmann::json& translations = data["translations"];
-    if (!translations.is_array() || translations.size() == 0)
+    const boost::json::value& translations = data.at("translations");
+    if (!translations.is_array() || translations.as_array().size() == 0)
     {
         return false;
     }
 
-    const nlohmann::json& first = translations[0U];
-    if (!first.is_object() || first.find("text") == first.end())
+    const boost::json::value& first = translations.at(0U);
+    if (!first.is_object() || !first.as_object().contains("text"))
     {
         return false;
     }
 
-    translation = first["text"].get<std::string>();
+    translation = boost::json::value_to<std::string>(first.at("text"));
 
     return true;
 }
@@ -755,29 +745,26 @@ std::string LLAzureTranslationHandler::parseErrorResponse(
     // Expected: "{\"error\":{\"code\":400000,\"message\":\"One of the request inputs is not valid.\"}}"
     // But for now just verify response is a valid json with an error
 
-	nlohmann::json root;
-    try
+    boost::json::error_code ec;
+    boost::json::value root = boost::json::parse(body, ec);
+    if (ec.failed())
     {
-		root = nlohmann::json::parse(body);
-    }
-    catch(const nlohmann::json::exception&)
-	{
         return std::string();
-	}
+    }
 
-    if (!root.is_object() || root.find("error") == root.end())
+    if (!root.is_object() || !root.as_object().contains("error"))
     {
         return std::string();
     }
 
-    const nlohmann::json& error_map = root["error"];
+    const boost::json::value& error_map = root.at("error");
 
-    if (!error_map.is_object() || error_map.find("message") == error_map.end())
+    if (!error_map.is_object() || !error_map.as_object().contains("message"))
     {
         return std::string();
     }
 
-    return error_map["message"].get<std::string>();
+    return boost::json::value_to<std::string>(error_map.at("message"));
 }
 
 // static
@@ -984,41 +971,38 @@ bool LLDeepLTranslationHandler::parseResponse(
     //Example:
     // "{\"translations\":[{\"detected_source_language\":\"EN\",\"text\":\"test\"}]}"
 
-	nlohmann::json root;
-    try
+    boost::json::error_code ec;
+    boost::json::value root = boost::json::parse(body, ec);
+    if (ec.failed())
     {
-		root = nlohmann::json::parse(body);
-    }
-    catch(nlohmann::json::exception &e)
-	{
-        err_msg = e.what();
+        err_msg = ec.message();
         return false;
-	}
+    }
 
     if (!root.is_object()
-        || root.find("translations") == root.end()) // empty response? should not happen
+        || !root.as_object().contains("translations")) // empty response? should not happen
     {
         return false;
     }
 
     // Request succeeded, extract translation from the response.
-    const nlohmann::json& translations = root["translations"];
-    if (!translations.is_array() || translations.size() == 0)
+    const boost::json::value& translations = root.at("translations");
+    if (!translations.is_array() || translations.as_array().size() == 0)
     {
         return false;
     }
 
-    const nlohmann::json& data= translations[0U];
+    const boost::json::value& data= translations.at(0U);
     if (!data.is_object()
-        || data.find("detected_source_language") == data.end()
-        || data.find("text") == data.end())
+        || !data.as_object().contains("detected_source_language")
+        || !data.as_object().contains("text"))
     {
         return false;
     }
 
-    detected_lang = data["detected_source_language"].get<std::string>();
+    detected_lang = boost::json::value_to<std::string>(root.at("detected_source_language"));
     LLStringUtil::toLower(detected_lang);
-    translation = data["text"].get<std::string>();
+    translation = boost::json::value_to<std::string>(root.at("text"));
 
     return true;
 }
@@ -1034,22 +1018,19 @@ std::string LLDeepLTranslationHandler::parseErrorResponse(
     const std::string& body)
 {
     // Example: "{\"message\":\"One of the request inputs is not valid.\"}"
-	nlohmann::json root;
-    try
-    {
-		root = nlohmann::json::parse(body);
-    }
-    catch(const nlohmann::json::exception &)
-	{
+    boost::json::error_code ec;
+    boost::json::value root = boost::json::parse(body, ec);
+    if (ec.failed())
+    {   
         return {};
-	}
+    }
 
-    if (!root.is_object() || root.find("message") == root.end())
+    if (!root.is_object() || !root.as_object().contains("message"))
     {
         return std::string();
     }
 
-    return root["message"].get<std::string>();
+    return boost::json::value_to<std::string>(root.at("message"));
 }
 
 // static