diff --git a/doc/examples/get__PointerType.cpp b/doc/examples/get__PointerType.cpp
new file mode 100644
index 00000000..e4dcec62
--- /dev/null
+++ b/doc/examples/get__PointerType.cpp
@@ -0,0 +1,20 @@
+#include <json.hpp>
+
+using namespace nlohmann;
+
+int main()
+{
+    // create a JSON boolean
+    json value = 17;
+
+    // explicitly getting pointers
+    auto p1 = value.get<const json::number_integer_t*>();
+    auto p2 = value.get<json::number_integer_t*>();
+    auto p3 = value.get<json::number_integer_t* const>();
+    auto p4 = value.get<const json::number_integer_t* const>();
+    auto p5 = value.get<json::number_float_t*>();
+
+    // print the pointees
+    std::cout << *p1 << ' ' << *p2 << ' ' << *p3 << ' ' << *p4 << '\n';
+    std::cout << std::boolalpha << (p5 == nullptr) << '\n';
+}
diff --git a/doc/examples/get__PointerType.output b/doc/examples/get__PointerType.output
new file mode 100644
index 00000000..a15dd774
--- /dev/null
+++ b/doc/examples/get__PointerType.output
@@ -0,0 +1,2 @@
+17 17 17 17
+true
diff --git a/doc/examples/get__ValueType_const.cpp b/doc/examples/get__ValueType_const.cpp
new file mode 100644
index 00000000..3ccba548
--- /dev/null
+++ b/doc/examples/get__ValueType_const.cpp
@@ -0,0 +1,49 @@
+#include <json.hpp>
+#include <unordered_map>
+
+using namespace nlohmann;
+
+int main()
+{
+    // create a JSON value with different types
+    json json_types =
+    {
+        {"boolean", true},
+        {
+            "number", {
+                {"integer", 42},
+                {"floating-point", 17.23}
+            }
+        },
+        {"string", "Hello, world!"},
+        {"array", {1, 2, 3, 4, 5}},
+        {"null", nullptr}
+    };
+
+    // use explicit conversions
+    auto v1 = json_types["boolean"].get<bool>();
+    auto v2 = json_types["number"]["integer"].get<int>();
+    auto v3 = json_types["number"]["integer"].get<short>();
+    auto v4 = json_types["number"]["floating-point"].get<float>();
+    auto v5 = json_types["number"]["floating-point"].get<int>();
+    auto v6 = json_types["string"].get<std::string>();
+    auto v7 = json_types["array"].get<std::vector<short>>();
+    auto v8 = json_types.get<std::unordered_map<std::string, json>>();
+
+    // print the conversion results
+    std::cout << v1 << '\n';
+    std::cout << v2 << ' ' << v3 << '\n';
+    std::cout << v4 << ' ' << v5 << '\n';
+    std::cout << v6 << '\n';
+
+    for (auto i : v7)
+    {
+        std::cout << i << ' ';
+    }
+    std::cout << "\n\n";
+
+    for (auto i : v8)
+    {
+        std::cout << i.first << ": " << i.second << '\n';
+    }
+}
diff --git a/doc/examples/get__ValueType_const.output b/doc/examples/get__ValueType_const.output
new file mode 100644
index 00000000..5cd9cd3a
--- /dev/null
+++ b/doc/examples/get__ValueType_const.output
@@ -0,0 +1,11 @@
+1
+42 42
+17.23 17
+Hello, world!
+1 2 3 4 5 
+
+string: "Hello, world!"
+number: {"floating-point":17.23,"integer":42}
+null: null
+boolean: true
+array: [1,2,3,4,5]
diff --git a/doc/examples/get_ptr.cpp b/doc/examples/get_ptr.cpp
new file mode 100644
index 00000000..ddbdfc00
--- /dev/null
+++ b/doc/examples/get_ptr.cpp
@@ -0,0 +1,20 @@
+#include <json.hpp>
+
+using namespace nlohmann;
+
+int main()
+{
+    // create a JSON boolean
+    json value = 17;
+
+    // explicitly getting pointers
+    auto p1 = value.get_ptr<const json::number_integer_t*>();
+    auto p2 = value.get_ptr<json::number_integer_t*>();
+    auto p3 = value.get_ptr<json::number_integer_t* const>();
+    auto p4 = value.get_ptr<const json::number_integer_t* const>();
+    auto p5 = value.get_ptr<json::number_float_t*>();
+
+    // print the pointees
+    std::cout << *p1 << ' ' << *p2 << ' ' << *p3 << ' ' << *p4 << '\n';
+    std::cout << std::boolalpha << (p5 == nullptr) << '\n';
+}
diff --git a/doc/examples/get_ptr.output b/doc/examples/get_ptr.output
new file mode 100644
index 00000000..a15dd774
--- /dev/null
+++ b/doc/examples/get_ptr.output
@@ -0,0 +1,2 @@
+17 17 17 17
+true
diff --git a/doc/examples/operator__ValueType.cpp b/doc/examples/operator__ValueType.cpp
new file mode 100644
index 00000000..962b4bf6
--- /dev/null
+++ b/doc/examples/operator__ValueType.cpp
@@ -0,0 +1,49 @@
+#include <json.hpp>
+#include <unordered_map>
+
+using namespace nlohmann;
+
+int main()
+{
+    // create a JSON value with different types
+    json json_types =
+    {
+        {"boolean", true},
+        {
+            "number", {
+                {"integer", 42},
+                {"floating-point", 17.23}
+            }
+        },
+        {"string", "Hello, world!"},
+        {"array", {1, 2, 3, 4, 5}},
+        {"null", nullptr}
+    };
+
+    // use implicit conversions
+    bool v1 = json_types["boolean"];
+    int v2 = json_types["number"]["integer"];
+    short v3 = json_types["number"]["integer"];
+    float v4 = json_types["number"]["floating-point"];
+    int v5 = json_types["number"]["floating-point"];
+    std::string v6 = json_types["string"];
+    std::vector<short> v7 = json_types["array"];
+    std::unordered_map<std::string, json> v8 = json_types;
+
+    // print the conversion results
+    std::cout << v1 << '\n';
+    std::cout << v2 << ' ' << v3 << '\n';
+    std::cout << v4 << ' ' << v5 << '\n';
+    std::cout << v6 << '\n';
+
+    for (auto i : v7)
+    {
+        std::cout << i << ' ';
+    }
+    std::cout << "\n\n";
+
+    for (auto i : v8)
+    {
+        std::cout << i.first << ": " << i.second << '\n';
+    }
+}
diff --git a/doc/examples/operator__ValueType.output b/doc/examples/operator__ValueType.output
new file mode 100644
index 00000000..5cd9cd3a
--- /dev/null
+++ b/doc/examples/operator__ValueType.output
@@ -0,0 +1,11 @@
+1
+42 42
+17.23 17
+Hello, world!
+1 2 3 4 5 
+
+string: "Hello, world!"
+number: {"floating-point":17.23,"integer":42}
+null: null
+boolean: true
+array: [1,2,3,4,5]
diff --git a/src/json.hpp b/src/json.hpp
index ed4d24fd..d2f62209 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -1787,24 +1787,192 @@ class basic_json
         }
     }
 
+    /// get a pointer to the value (object)
+    const object_t* get_impl_ptr(object_t*) const noexcept
+    {
+        return is_object() ? m_value.object : nullptr;
+    }
+
+    /// get a pointer to the value (array)
+    const array_t* get_impl_ptr(array_t*) const noexcept
+    {
+        return is_array() ? m_value.array : nullptr;
+    }
+
+    /// get a pointer to the value (string)
+    const string_t* get_impl_ptr(string_t*) const noexcept
+    {
+        return is_string() ? m_value.string : nullptr;
+    }
+
+    /// get a pointer to the value (boolean)
+    const boolean_t* get_impl_ptr(boolean_t*) const noexcept
+    {
+        return is_boolean() ? &m_value.boolean : nullptr;
+    }
+
+    /// get a pointer to the value (integer number)
+    const number_integer_t* get_impl_ptr(number_integer_t*) const noexcept
+    {
+        return is_number_integer() ? &m_value.number_integer : nullptr;
+    }
+
+    /// get a pointer to the value (floating-point number)
+    const number_float_t* get_impl_ptr(number_float_t*) const noexcept
+    {
+        return is_number_float() ? &m_value.number_float : nullptr;
+    }
+
   public:
 
     /// @name value access
     /// @{
 
-    /// get a value (explicit)
-    // <http://stackoverflow.com/a/8315197/266378>
-    template<typename T>
-    T get() const
+    /*!
+    @brief get a value (explicit)
+
+    Explicit type conversion between the JSON value and a compatible value.
+
+    @tparam ValueType non-pointer type compatible to the JSON value, for
+    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+    `std::vector` types for JSON arrays
+
+    @return copy of the JSON value, converted to type @a ValueType
+
+    @throw std::domain_error in case passed type @a ValueType is incompatible
+    to JSON
+
+    @complexity Linear in the size of the JSON value.
+
+    @liveexample{The example below shows serveral conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    assiciative containers such as `std::unordered_map<std::string\,
+    json>`.,get__ValueType_const}
+
+    @internal
+    The idea of using a casted null pointer to choose the correct
+    implementation is from <http://stackoverflow.com/a/8315197/266378>.
+    @endinternal
+
+    @sa @ref operator ValueType() const for implicit conversion
+    @sa @ref get() for pointer-member access
+    */
+    template<typename ValueType, typename
+             std::enable_if<
+                 not std::is_pointer<ValueType>::value
+                 , int>::type = 0>
+    ValueType get() const
     {
-        return get_impl(static_cast<T*>(nullptr));
+        return get_impl(static_cast<ValueType*>(nullptr));
     }
 
-    /// get a value (implicit)
-    template<typename T>
-    operator T() const
+    /*!
+    @brief get a pointer value (explicit)
+
+    Explicit pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning Writing data to the pointee of the result yields an undefined
+    state.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
+    number_float_t.
+
+    @return pointer to the internally stored JSON value if the requested pointer
+    type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get__PointerType}
+
+    @sa @ref get_ptr() for explicit pointer-member access
+    */
+    template<typename PointerType, typename
+             std::enable_if<
+                 std::is_pointer<PointerType>::value
+                 , int>::type = 0>
+    PointerType get() const noexcept
     {
-        return get<T>();
+        // delegate the call to get_ptr
+        return get_ptr<PointerType>();
+    }
+
+    /*!
+    @brief get a pointer value (implicit)
+
+    Implict pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning Writing data to the pointee of the result yields an undefined
+    state.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
+    number_float_t.
+
+    @return pointer to the internally stored JSON value if the requested pointer
+    type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get_ptr}
+    */
+    template<typename PointerType, typename
+             std::enable_if<
+                 std::is_pointer<PointerType>::value
+                 , int>::type = 0>
+    PointerType get_ptr() const noexcept
+    {
+        // get_impl_ptr will only work with non-const and non-volatile pointer
+        // types. Therefore, we case away all cv properties to be able to
+        // select the correct function. The cv properties will then be added
+        // again by the const const cast to PointerType.
+        return const_cast<PointerType>(get_impl_ptr(
+                                           static_cast<typename std::add_pointer<typename std::remove_cv<typename std::remove_pointer<PointerType>::type>::type>::type>
+                                           (nullptr)));
+    }
+
+    /*!
+    @brief get a value (implicit)
+
+    Implict type conversion between the JSON value and a compatible value. The
+    call is realized by calling @ref get() const.
+
+    @tparam ValueType non-pointer type compatible to the JSON value, for
+    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+    `std::vector` types for JSON arrays
+
+    @return copy of the JSON value, converted to type @a ValueType
+
+    @throw std::domain_error in case passed type @a ValueType is incompatible
+    to JSON, thrown by @ref get() const
+
+    @complexity Linear in the size of the JSON value.
+
+    @liveexample{The example below shows serveral conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    assiciative containers such as `std::unordered_map<std::string\,
+    json>`.,operator__ValueType}
+    */
+    template<typename ValueType, typename
+             std::enable_if<
+                 not std::is_pointer<ValueType>::value
+                 , int>::type = 0>
+    operator ValueType() const
+    {
+        // delegate the call to get<>() const
+        return get<ValueType>();
     }
 
     /// @}
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 4c574e6f..fed27c1d 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -1787,24 +1787,192 @@ class basic_json
         }
     }
 
+    /// get a pointer to the value (object)
+    const object_t* get_impl_ptr(object_t*) const noexcept
+    {
+        return is_object() ? m_value.object : nullptr;
+    }
+
+    /// get a pointer to the value (array)
+    const array_t* get_impl_ptr(array_t*) const noexcept
+    {
+        return is_array() ? m_value.array : nullptr;
+    }
+
+    /// get a pointer to the value (string)
+    const string_t* get_impl_ptr(string_t*) const noexcept
+    {
+        return is_string() ? m_value.string : nullptr;
+    }
+
+    /// get a pointer to the value (boolean)
+    const boolean_t* get_impl_ptr(boolean_t*) const noexcept
+    {
+        return is_boolean() ? &m_value.boolean : nullptr;
+    }
+
+    /// get a pointer to the value (integer number)
+    const number_integer_t* get_impl_ptr(number_integer_t*) const noexcept
+    {
+        return is_number_integer() ? &m_value.number_integer : nullptr;
+    }
+
+    /// get a pointer to the value (floating-point number)
+    const number_float_t* get_impl_ptr(number_float_t*) const noexcept
+    {
+        return is_number_float() ? &m_value.number_float : nullptr;
+    }
+
   public:
 
     /// @name value access
     /// @{
 
-    /// get a value (explicit)
-    // <http://stackoverflow.com/a/8315197/266378>
-    template<typename T>
-    T get() const
+    /*!
+    @brief get a value (explicit)
+
+    Explicit type conversion between the JSON value and a compatible value.
+
+    @tparam ValueType non-pointer type compatible to the JSON value, for
+    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+    `std::vector` types for JSON arrays
+
+    @return copy of the JSON value, converted to type @a ValueType
+
+    @throw std::domain_error in case passed type @a ValueType is incompatible
+    to JSON
+
+    @complexity Linear in the size of the JSON value.
+
+    @liveexample{The example below shows serveral conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    assiciative containers such as `std::unordered_map<std::string\,
+    json>`.,get__ValueType_const}
+
+    @internal
+    The idea of using a casted null pointer to choose the correct
+    implementation is from <http://stackoverflow.com/a/8315197/266378>.
+    @endinternal
+
+    @sa @ref operator ValueType() const for implicit conversion
+    @sa @ref get() for pointer-member access
+    */
+    template<typename ValueType, typename
+             std::enable_if<
+                 not std::is_pointer<ValueType>::value
+                 , int>::type = 0>
+    ValueType get() const
     {
-        return get_impl(static_cast<T*>(nullptr));
+        return get_impl(static_cast<ValueType*>(nullptr));
     }
 
-    /// get a value (implicit)
-    template<typename T>
-    operator T() const
+    /*!
+    @brief get a pointer value (explicit)
+
+    Explicit pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning Writing data to the pointee of the result yields an undefined
+    state.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
+    number_float_t.
+
+    @return pointer to the internally stored JSON value if the requested pointer
+    type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get__PointerType}
+
+    @sa @ref get_ptr() for explicit pointer-member access
+    */
+    template<typename PointerType, typename
+             std::enable_if<
+                 std::is_pointer<PointerType>::value
+                 , int>::type = 0>
+    PointerType get() const noexcept
     {
-        return get<T>();
+        // delegate the call to get_ptr
+        return get_ptr<PointerType>();
+    }
+
+    /*!
+    @brief get a pointer value (implicit)
+
+    Implict pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning Writing data to the pointee of the result yields an undefined
+    state.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
+    number_float_t.
+
+    @return pointer to the internally stored JSON value if the requested pointer
+    type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get_ptr}
+    */
+    template<typename PointerType, typename
+             std::enable_if<
+                 std::is_pointer<PointerType>::value
+                 , int>::type = 0>
+    PointerType get_ptr() const noexcept
+    {
+        // get_impl_ptr will only work with non-const and non-volatile pointer
+        // types. Therefore, we case away all cv properties to be able to
+        // select the correct function. The cv properties will then be added
+        // again by the const const cast to PointerType.
+        return const_cast<PointerType>(get_impl_ptr(
+                                           static_cast<typename std::add_pointer<typename std::remove_cv<typename std::remove_pointer<PointerType>::type>::type>::type>
+                                           (nullptr)));
+    }
+
+    /*!
+    @brief get a value (implicit)
+
+    Implict type conversion between the JSON value and a compatible value. The
+    call is realized by calling @ref get() const.
+
+    @tparam ValueType non-pointer type compatible to the JSON value, for
+    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+    `std::vector` types for JSON arrays
+
+    @return copy of the JSON value, converted to type @a ValueType
+
+    @throw std::domain_error in case passed type @a ValueType is incompatible
+    to JSON, thrown by @ref get() const
+
+    @complexity Linear in the size of the JSON value.
+
+    @liveexample{The example below shows serveral conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    assiciative containers such as `std::unordered_map<std::string\,
+    json>`.,operator__ValueType}
+    */
+    template<typename ValueType, typename
+             std::enable_if<
+                 not std::is_pointer<ValueType>::value
+                 , int>::type = 0>
+    operator ValueType() const
+    {
+        // delegate the call to get<>() const
+        return get<ValueType>();
     }
 
     /// @}
diff --git a/test/unit.cpp b/test/unit.cpp
index c8074b34..b0d20ef4 100644
--- a/test/unit.cpp
+++ b/test/unit.cpp
@@ -2434,6 +2434,186 @@ TEST_CASE("value conversion")
     }
 }
 
+TEST_CASE("pointer access")
+{
+    // create a JSON value with different types
+    json json_types =
+    {
+        {"boolean", true},
+        {
+            "number", {
+                {"integer", 42},
+                {"floating-point", 17.23}
+            }
+        },
+        {"string", "Hello, world!"},
+        {"array", {1, 2, 3, 4, 5}},
+        {"null", nullptr}
+    };
+
+    SECTION("pointer access to object_t")
+    {
+        using test_type = json::object_t;
+        json value = {{"one", 1}, {"two", 2}};
+
+        // check if pointers are returned correctly
+        test_type* p1 = value.get_ptr<test_type*>();
+        CHECK(p1 == value.get_ptr<test_type*>());
+        CHECK(*p1 == value.get<test_type>());
+
+        const test_type* p2 = value.get_ptr<const test_type*>();
+        CHECK(p1 == value.get_ptr<const test_type*>());
+        CHECK(*p2 == value.get<test_type>());
+
+        const test_type* const p3 = value.get_ptr<const test_type* const>();
+        CHECK(p1 == value.get_ptr<const test_type* const>());
+        CHECK(*p3 == value.get<test_type>());
+
+        // check if null pointers are returned correctly
+        CHECK(value.get_ptr<json::object_t*>() != nullptr);
+        CHECK(value.get_ptr<json::array_t*>() == nullptr);
+        CHECK(value.get_ptr<json::string_t*>() == nullptr);
+        CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
+    }
+
+    SECTION("pointer access to array_t")
+    {
+        using test_type = json::array_t;
+        json value = {1, 2, 3, 4};
+
+        // check if pointers are returned correctly
+        test_type* p1 = value.get_ptr<test_type*>();
+        CHECK(p1 == value.get_ptr<test_type*>());
+        CHECK(*p1 == value.get<test_type>());
+
+        const test_type* p2 = value.get_ptr<const test_type*>();
+        CHECK(p1 == value.get_ptr<const test_type*>());
+        CHECK(*p2 == value.get<test_type>());
+
+        const test_type* const p3 = value.get_ptr<const test_type* const>();
+        CHECK(p1 == value.get_ptr<const test_type* const>());
+        CHECK(*p3 == value.get<test_type>());
+
+        // check if null pointers are returned correctly
+        CHECK(value.get_ptr<json::object_t*>() == nullptr);
+        CHECK(value.get_ptr<json::array_t*>() != nullptr);
+        CHECK(value.get_ptr<json::string_t*>() == nullptr);
+        CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
+    }
+
+    SECTION("pointer access to string_t")
+    {
+        using test_type = json::string_t;
+        json value = "hello";
+
+        // check if pointers are returned correctly
+        test_type* p1 = value.get_ptr<test_type*>();
+        CHECK(p1 == value.get_ptr<test_type*>());
+        CHECK(*p1 == value.get<test_type>());
+
+        const test_type* p2 = value.get_ptr<const test_type*>();
+        CHECK(p1 == value.get_ptr<const test_type*>());
+        CHECK(*p2 == value.get<test_type>());
+
+        const test_type* const p3 = value.get_ptr<const test_type* const>();
+        CHECK(p1 == value.get_ptr<const test_type* const>());
+        CHECK(*p3 == value.get<test_type>());
+
+        // check if null pointers are returned correctly
+        CHECK(value.get_ptr<json::object_t*>() == nullptr);
+        CHECK(value.get_ptr<json::array_t*>() == nullptr);
+        CHECK(value.get_ptr<json::string_t*>() != nullptr);
+        CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
+    }
+
+    SECTION("pointer access to boolean_t")
+    {
+        using test_type = json::boolean_t;
+        json value = false;
+
+        // check if pointers are returned correctly
+        test_type* p1 = value.get_ptr<test_type*>();
+        CHECK(p1 == value.get_ptr<test_type*>());
+        CHECK(*p1 == value.get<test_type>());
+
+        const test_type* p2 = value.get_ptr<const test_type*>();
+        CHECK(p1 == value.get_ptr<const test_type*>());
+        CHECK(*p2 == value.get<test_type>());
+
+        const test_type* const p3 = value.get_ptr<const test_type* const>();
+        CHECK(p1 == value.get_ptr<const test_type* const>());
+        CHECK(*p3 == value.get<test_type>());
+
+        // check if null pointers are returned correctly
+        CHECK(value.get_ptr<json::object_t*>() == nullptr);
+        CHECK(value.get_ptr<json::array_t*>() == nullptr);
+        CHECK(value.get_ptr<json::string_t*>() == nullptr);
+        CHECK(value.get_ptr<json::boolean_t*>() != nullptr);
+        CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
+    }
+
+    SECTION("pointer access to number_integer_t")
+    {
+        using test_type = json::number_integer_t;
+        json value = 23;
+
+        // check if pointers are returned correctly
+        test_type* p1 = value.get_ptr<test_type*>();
+        CHECK(p1 == value.get_ptr<test_type*>());
+        CHECK(*p1 == value.get<test_type>());
+
+        const test_type* p2 = value.get_ptr<const test_type*>();
+        CHECK(p1 == value.get_ptr<const test_type*>());
+        CHECK(*p2 == value.get<test_type>());
+
+        const test_type* const p3 = value.get_ptr<const test_type* const>();
+        CHECK(p1 == value.get_ptr<const test_type* const>());
+        CHECK(*p3 == value.get<test_type>());
+
+        // check if null pointers are returned correctly
+        CHECK(value.get_ptr<json::object_t*>() == nullptr);
+        CHECK(value.get_ptr<json::array_t*>() == nullptr);
+        CHECK(value.get_ptr<json::string_t*>() == nullptr);
+        CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_integer_t*>() != nullptr);
+        CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
+    }
+
+    SECTION("pointer access to number_float_t")
+    {
+        using test_type = json::number_float_t;
+        json value = 42.23;
+
+        // check if pointers are returned correctly
+        test_type* p1 = value.get_ptr<test_type*>();
+        CHECK(p1 == value.get_ptr<test_type*>());
+        CHECK(*p1 == Approx(value.get<test_type>()));
+
+        const test_type* p2 = value.get_ptr<const test_type*>();
+        CHECK(p1 == value.get_ptr<const test_type*>());
+        CHECK(*p2 == Approx(value.get<test_type>()));
+
+        const test_type* const p3 = value.get_ptr<const test_type* const>();
+        CHECK(p1 == value.get_ptr<const test_type* const>());
+        CHECK(*p3 == Approx(value.get<test_type>()));
+
+        // check if null pointers are returned correctly
+        CHECK(value.get_ptr<json::object_t*>() == nullptr);
+        CHECK(value.get_ptr<json::array_t*>() == nullptr);
+        CHECK(value.get_ptr<json::string_t*>() == nullptr);
+        CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_float_t*>() != nullptr);
+    }
+}
+
 TEST_CASE("element access")
 {
     SECTION("array")