diff --git a/src/json.hpp b/src/json.hpp
index 63f5d2b8..7c4fec5b 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -1443,8 +1443,15 @@ class input_adapter
         : ia(std::make_shared<cached_input_stream_adapter<16384>>(i)) {}
 
     /// input adapter for buffer
-    input_adapter(const char* b, std::size_t l)
-        : ia(std::make_shared<input_buffer_adapter>(b, l)) {}
+    template <typename CharT,
+              typename std::enable_if<
+                  std::is_pointer<CharT>::value and
+                  std::is_integral<
+                      typename std::remove_pointer<CharT>::type>::value and
+                  sizeof(typename std::remove_pointer<CharT>::type) == 1,
+                  int>::type = 0>
+    input_adapter(CharT b, std::size_t l)
+        : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
 
     // derived support
 
@@ -4546,21 +4553,20 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
 /////////////////////
 
 /// abstract output adapter interface
-template <typename CharType> class output_adapter
+template <typename CharType> struct output_adapter_protocol
 {
-  public:
     virtual void write_character(CharType c) = 0;
     virtual void write_characters(const CharType* s, std::size_t length) = 0;
-    virtual ~output_adapter() = default;
+    virtual ~output_adapter_protocol() = default;
 };
 
 /// a type to simplify interfaces
 template <typename CharType>
-using output_adapter_t = std::shared_ptr<output_adapter<CharType>>;
+using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
 
 /// output adapter for byte vectors
 template <typename CharType>
-class output_vector_adapter : public output_adapter<CharType>
+class output_vector_adapter : public output_adapter_protocol<CharType>
 {
   public:
     explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {}
@@ -4581,7 +4587,7 @@ class output_vector_adapter : public output_adapter<CharType>
 
 /// output adapter for output streams
 template <typename CharType>
-class output_stream_adapter : public output_adapter<CharType>
+class output_stream_adapter : public output_adapter_protocol<CharType>
 {
   public:
     explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {}
@@ -4602,10 +4608,10 @@ class output_stream_adapter : public output_adapter<CharType>
 
 /// output adapter for basic_string
 template <typename CharType>
-class output_string_adapter : public output_adapter<CharType>
+class output_string_adapter : public output_adapter_protocol<CharType>
 {
   public:
-    explicit output_string_adapter(std::string& s) : str(s) {}
+    explicit output_string_adapter(std::basic_string<CharType>& s) : str(s) {}
 
     void write_character(CharType c) override
     {
@@ -4621,23 +4627,26 @@ class output_string_adapter : public output_adapter<CharType>
     std::basic_string<CharType>& str;
 };
 
-template <typename CharType> struct output_adapter_factory
+template <typename CharType>
+class output_adapter
 {
-    static std::shared_ptr<output_adapter<CharType>>
-            create(std::vector<CharType>& vec)
+  public:
+    output_adapter(std::vector<CharType>& vec)
+        : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
+
+    output_adapter(std::basic_ostream<CharType>& s)
+        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
+
+    output_adapter(std::basic_string<CharType>& s)
+        : oa(std::make_shared<output_string_adapter<CharType>>(s)) {}
+
+    operator output_adapter_t<CharType>()
     {
-        return std::make_shared<output_vector_adapter<CharType>>(vec);
+        return oa;
     }
 
-    static std::shared_ptr<output_adapter<CharType>> create(std::ostream& s)
-    {
-        return std::make_shared<output_stream_adapter<CharType>>(s);
-    }
-
-    static std::shared_ptr<output_adapter<CharType>> create(std::string& s)
-    {
-        return std::make_shared<output_string_adapter<CharType>>(s);
-    }
+  private:
+    output_adapter_t<CharType> oa = nullptr;
 };
 
 //////////////////////////////
@@ -9109,7 +9118,7 @@ class basic_json
                   const bool ensure_ascii = false) const
     {
         string_t result;
-        serializer s(detail::output_adapter_factory<char>::create(result), indent_char);
+        serializer s(detail::output_adapter<char>(result), indent_char);
 
         if (indent >= 0)
         {
@@ -12783,7 +12792,7 @@ class basic_json
         o.width(0);
 
         // do the actual serialization
-        serializer s(detail::output_adapter_factory<char>::create(o), o.fill());
+        serializer s(detail::output_adapter<char>(o), o.fill());
         s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
         return o;
     }
@@ -13162,11 +13171,15 @@ class basic_json
     static std::vector<uint8_t> to_cbor(const basic_json& j)
     {
         std::vector<uint8_t> result;
-        binary_writer bw(detail::output_adapter_factory<uint8_t>::create(result));
-        bw.write_cbor(j);
+        to_cbor(j, result);
         return result;
     }
 
+    static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
+    {
+        binary_writer(o).write_cbor(j);
+    }
+
     /*!
     @brief create a MessagePack serialization of a given JSON value
 
@@ -13244,11 +13257,20 @@ class basic_json
     static std::vector<uint8_t> to_msgpack(const basic_json& j)
     {
         std::vector<uint8_t> result;
-        binary_writer bw(detail::output_adapter_factory<uint8_t>::create(result));
-        bw.write_msgpack(j);
+        to_msgpack(j, result);
         return result;
     }
 
+    static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
+    {
+        binary_writer(o).write_msgpack(j);
+    }
+
+    static void to_msgpack(const basic_json& j, std::vector<uint8_t>& result)
+    {
+        binary_writer((detail::output_adapter<uint8_t>(result))).write_msgpack(j);
+    }
+
     /*!
     @brief create a JSON value from a byte vector in CBOR format
 
@@ -13343,6 +13365,11 @@ class basic_json
         return br.parse_cbor();
     }
 
+    static basic_json from_cbor(detail::input_adapter i)
+    {
+        return binary_reader(i).parse_cbor();
+    }
+
 
     /*!
     @brief create a JSON value from a byte vector in MessagePack format
@@ -13418,6 +13445,11 @@ class basic_json
         return br.parse_msgpack();
     }
 
+    static basic_json from_msgpack(detail::input_adapter i)
+    {
+        return binary_reader(i).parse_msgpack();
+    }
+
     /// @}
 
     //////////////////////////
diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp
index 5ab6a2e2..934ce55f 100644
--- a/test/src/unit-cbor.cpp
+++ b/test/src/unit-cbor.cpp
@@ -1519,16 +1519,60 @@ TEST_CASE("CBOR roundtrips", "[hide]")
             std::ifstream f_json(filename);
             json j1 = json::parse(f_json);
 
-            // parse CBOR file
-            std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
-            std::vector<uint8_t> packed(
-                (std::istreambuf_iterator<char>(f_cbor)),
-                std::istreambuf_iterator<char>());
-            json j2;
-            CHECK_NOTHROW(j2 = json::from_cbor(packed));
+            SECTION("std::vector<uint8_t>")
+            {
+                // parse CBOR file
+                std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
+                std::vector<uint8_t> packed(
+                    (std::istreambuf_iterator<char>(f_cbor)),
+                    std::istreambuf_iterator<char>());
+                json j2;
+                CHECK_NOTHROW(j2 = json::from_cbor(packed));
 
-            // compare parsed JSON values
-            CHECK(j1 == j2);
+                // compare parsed JSON values
+                CHECK(j1 == j2);
+            }
+
+            SECTION("std::ifstream")
+            {
+                // parse CBOR file
+                std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
+                json j2;
+                CHECK_NOTHROW(j2 = json::from_cbor(f_cbor));
+
+                // compare parsed JSON values
+                CHECK(j1 == j2);
+            }
+
+            SECTION("uint8_t* and size")
+            {
+                // parse CBOR file
+                std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
+                std::vector<uint8_t> packed(
+                    (std::istreambuf_iterator<char>(f_cbor)),
+                    std::istreambuf_iterator<char>());
+                json j2;
+                CHECK_NOTHROW(j2 = json::from_cbor({packed.data(), packed.size()}));
+
+                // compare parsed JSON values
+                CHECK(j1 == j2);
+            }
+
+            SECTION("output to output adapters")
+            {
+                // parse CBOR file
+                std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
+                std::vector<uint8_t> packed(
+                    (std::istreambuf_iterator<char>(f_cbor)),
+                    std::istreambuf_iterator<char>());
+
+                SECTION("std::vector<uint8_t>")
+                {
+                    std::vector<uint8_t> vec;
+                    json::to_cbor(j1, vec);
+                    CHECK(vec == packed);
+                }
+            }
         }
     }
 }
diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp
index cd4f9e3f..1faecce8 100644
--- a/test/src/unit-convenience.cpp
+++ b/test/src/unit-convenience.cpp
@@ -36,7 +36,7 @@ void check_escaped(const char* original, const char* escaped, const bool ensure_
 void check_escaped(const char* original, const char* escaped, const bool ensure_ascii)
 {
     std::stringstream ss;
-    json::serializer s(nlohmann::detail::output_adapter_factory<char>::create(ss), ' ');
+    json::serializer s(nlohmann::detail::output_adapter<char>(ss), ' ');
     s.dump_escaped(original, ensure_ascii);
     CHECK(ss.str() == escaped);
 }
diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp
index baef3e35..f4b40354 100644
--- a/test/src/unit-msgpack.cpp
+++ b/test/src/unit-msgpack.cpp
@@ -1292,15 +1292,60 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
             std::ifstream f_json(filename);
             json j1 = json::parse(f_json);
 
-            // parse MessagePack file
-            std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
-            std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_msgpack)),
-                                        std::istreambuf_iterator<char>());
-            json j2;
-            CHECK_NOTHROW(j2 = json::from_msgpack(packed));
+            SECTION("std::vector<uint8_t>")
+            {
+                // parse MessagePack file
+                std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
+                std::vector<uint8_t> packed(
+                    (std::istreambuf_iterator<char>(f_msgpack)),
+                    std::istreambuf_iterator<char>());
+                json j2;
+                CHECK_NOTHROW(j2 = json::from_msgpack(packed));
 
-            // compare parsed JSON values
-            CHECK(j1 == j2);
+                // compare parsed JSON values
+                CHECK(j1 == j2);
+            }
+
+            SECTION("std::ifstream")
+            {
+                // parse MessagePack file
+                std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
+                json j2;
+                CHECK_NOTHROW(j2 = json::from_msgpack(f_msgpack));
+
+                // compare parsed JSON values
+                CHECK(j1 == j2);
+            }
+
+            SECTION("uint8_t* and size")
+            {
+                // parse MessagePack file
+                std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
+                std::vector<uint8_t> packed(
+                    (std::istreambuf_iterator<char>(f_msgpack)),
+                    std::istreambuf_iterator<char>());
+                json j2;
+                CHECK_NOTHROW(j2 = json::from_msgpack({packed.data(), packed.size()}));
+
+                // compare parsed JSON values
+                CHECK(j1 == j2);
+            }
+
+            SECTION("output to output adapters")
+            {
+                // parse MessagePack file
+                std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
+                std::vector<uint8_t> packed(
+                    (std::istreambuf_iterator<char>(f_msgpack)),
+                    std::istreambuf_iterator<char>());
+
+                SECTION("std::vector<uint8_t>")
+                {
+                    std::vector<uint8_t> vec;
+                    json::to_msgpack(j1, vec);
+                    CHECK(vec == packed);
+                }
+            }
         }
     }
 }