diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp
index e6811ceb..0a4ddbda 100644
--- a/include/nlohmann/detail/output/serializer.hpp
+++ b/include/nlohmann/detail/output/serializer.hpp
@@ -630,7 +630,7 @@ class serializer
         if (is_negative)
         {
             *buffer_ptr = '-';
-            abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
+            abs_value = remove_sign(x);
 
             // account one more byte for the minus sign
             n_chars = 1 + count_digits(abs_value);
@@ -811,6 +811,32 @@ class serializer
         return state;
     }
 
+    /*
+     * Overload to make the compiler happy while it is instantiating
+     * dump_integer for number_unsigned_t.
+     * Must never be called.
+     */
+    number_unsigned_t remove_sign(number_unsigned_t x)
+    {
+        assert(false); // LCOV_EXCL_LINE
+        return x; // LCOV_EXCL_LINE
+    }
+
+    /*
+     * Helper function for dump_integer
+     *
+     * This function takes a negative signed integer and returns its absolute
+     * value as unsigned integer. The plus/minus shuffling is necessary as we can
+     * not directly remove the sign of an arbitrary signed integer as the
+     * absolute values of INT_MIN and INT_MAX are usually not the same. See
+     * #1708 for details.
+     */
+    inline number_unsigned_t remove_sign(number_integer_t x) noexcept
+    {
+        assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
+        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
+    }
+
   private:
     /// the output of the serializer
     output_adapter_t<char> o = nullptr;
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index e54c3e41..31702a9f 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -14267,7 +14267,7 @@ class serializer
         if (is_negative)
         {
             *buffer_ptr = '-';
-            abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
+            abs_value = remove_sign(x);
 
             // account one more byte for the minus sign
             n_chars = 1 + count_digits(abs_value);
@@ -14448,6 +14448,32 @@ class serializer
         return state;
     }
 
+    /*
+     * Overload to make the compiler happy while it is instantiating
+     * dump_integer for number_unsigned_t.
+     * Must never be called.
+     */
+    number_unsigned_t remove_sign(number_unsigned_t x)
+    {
+        assert(false); // LCOV_EXCL_LINE
+        return x; // LCOV_EXCL_LINE
+    }
+
+    /*
+     * Helper function for dump_integer
+     *
+     * This function takes a negative signed integer and returns its absolute
+     * value as unsigned integer. The plus/minus shuffling is necessary as we can
+     * not directly remove the sign of an arbitrary signed integer as the
+     * absolute values of INT_MIN and INT_MAX are usually not the same. See
+     * #1708 for details.
+     */
+    inline number_unsigned_t remove_sign(number_integer_t x) noexcept
+    {
+        assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
+        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
+    }
+
   private:
     /// the output of the serializer
     output_adapter_t<char> o = nullptr;
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index 866a985b..c9e8b0d7 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -1802,6 +1802,13 @@ TEST_CASE("regression tests")
         json j = json::parse("[-9223372036854775808]");
         CHECK(j.dump() == "[-9223372036854775808]");
     }
+
+    SECTION("issue #1708 - minimum value of int64_t can be outputted")
+    {
+        constexpr auto smallest = (std::numeric_limits<int64_t>::min)();
+        json j = smallest;
+        CHECK(j.dump() == std::to_string(smallest));
+    }
 }
 
 #if not defined(JSON_NOEXCEPTION)
diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp
index 3a0b28e4..dadec343 100644
--- a/test/src/unit-serialization.cpp
+++ b/test/src/unit-serialization.cpp
@@ -189,3 +189,20 @@ TEST_CASE("serialization")
         test("[3,\"false\",false]", "[3,\\\"false\\\",false]");
     }
 }
+
+TEST_CASE_TEMPLATE("serialization for extreme integer values", T, int32_t, uint32_t, int64_t, uint64_t)
+{
+    SECTION("minimum")
+    {
+        constexpr auto minimum = (std::numeric_limits<T>::min)();
+        json j = minimum;
+        CHECK(j.dump() == std::to_string(minimum));
+    }
+
+    SECTION("maximum")
+    {
+        constexpr auto maximum = (std::numeric_limits<T>::max)();
+        json j = maximum;
+        CHECK(j.dump() == std::to_string(maximum));
+    }
+}