diff --git a/README.md b/README.md
index 962e9dda..bc156057 100644
--- a/README.md
+++ b/README.md
@@ -515,17 +515,17 @@ To compile and run the tests, you need to execute
 $ make check
 
 ===============================================================================
-All tests passed (8905161 assertions in 35 test cases)
+All tests passed (8905166 assertions in 35 test cases)
 ```
 
 Alternatively, you can use [https://cmake.org](CMake) and run
 
 ```sh
-mkdir build
-cd build
-cmake ..
-make
-ctest
+$ mkdir build
+$ cd build
+$ cmake ..
+$ make
+$ ctest
 ```
 
 For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
diff --git a/doc/examples/operatorjson_pointer.cpp b/doc/examples/operatorjson_pointer.cpp
index 18e41c1f..d7e8faff 100644
--- a/doc/examples/operatorjson_pointer.cpp
+++ b/doc/examples/operatorjson_pointer.cpp
@@ -40,7 +40,7 @@ int main()
     // output the changed array
     std::cout << j["array"] << '\n';
 
-    // "change" the arry element past the end
+    // "change" the array element past the end
     j["/array/-"_json_pointer] = 55;
     // output the changed array
     std::cout << j["array"] << '\n';
diff --git a/src/json.hpp b/src/json.hpp
index 04c8573f..78cc7093 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -32,6 +32,7 @@ SOFTWARE.
 #include <algorithm>
 #include <array>
 #include <cassert>
+#include <cctype>
 #include <ciso646>
 #include <cmath>
 #include <cstddef>
@@ -9436,6 +9437,12 @@ basic_json_parser_63:
         /*!
         @brief return a reference to the pointed to value
 
+        @note This version does not throw if a value is not present, but tries
+        to create nested values instead. For instance, calling this function
+        with pointer `"/this/that"` on a null value is equivalent to calling
+        `operator[]("this").operator[]("that")` on that value, effectively
+        changing the null value to an object.
+
         @param[in] ptr  a JSON value
 
         @return reference to the JSON value pointed to by the JSON pointer
@@ -9450,6 +9457,29 @@ basic_json_parser_63:
         {
             for (const auto& reference_token : reference_tokens)
             {
+                // convert null values to arrays or objects before continuing
+                if (ptr->m_type == value_t::null)
+                {
+                    // check if reference token is a number
+                    const bool nums = std::all_of(reference_token.begin(),
+                                                  reference_token.end(),
+                                                  [](const char x)
+                    {
+                        return std::isdigit(x);
+                    });
+
+                    // change value to array for numbers or "-" or to object
+                    // otherwise
+                    if (nums or reference_token == "-")
+                    {
+                        *ptr = value_t::array;
+                    }
+                    else
+                    {
+                        *ptr = value_t::object;
+                    }
+                }
+
                 switch (ptr->m_type)
                 {
                     case value_t::object:
@@ -9461,6 +9491,7 @@ basic_json_parser_63:
 
                     case value_t::array:
                     {
+
                         // error condition (cf. RFC 6901, Sect. 4)
                         if (reference_token.size() > 1 and reference_token[0] == '0')
                         {
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 48224835..61196844 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -32,6 +32,7 @@ SOFTWARE.
 #include <algorithm>
 #include <array>
 #include <cassert>
+#include <cctype>
 #include <ciso646>
 #include <cmath>
 #include <cstddef>
@@ -8733,6 +8734,12 @@ class basic_json
         /*!
         @brief return a reference to the pointed to value
 
+        @note This version does not throw if a value is not present, but tries
+        to create nested values instead. For instance, calling this function
+        with pointer `"/this/that"` on a null value is equivalent to calling
+        `operator[]("this").operator[]("that")` on that value, effectively
+        changing the null value to an object.
+
         @param[in] ptr  a JSON value
 
         @return reference to the JSON value pointed to by the JSON pointer
@@ -8747,6 +8754,29 @@ class basic_json
         {
             for (const auto& reference_token : reference_tokens)
             {
+                // convert null values to arrays or objects before continuing
+                if (ptr->m_type == value_t::null)
+                {
+                    // check if reference token is a number
+                    const bool nums = std::all_of(reference_token.begin(),
+                                                  reference_token.end(),
+                                                  [](const char x)
+                    {
+                        return std::isdigit(x);
+                    });
+
+                    // change value to array for numbers or "-" or to object
+                    // otherwise
+                    if (nums or reference_token == "-")
+                    {
+                        *ptr = value_t::array;
+                    }
+                    else
+                    {
+                        *ptr = value_t::object;
+                    }
+                }
+
                 switch (ptr->m_type)
                 {
                     case value_t::object:
@@ -8758,6 +8788,7 @@ class basic_json
 
                     case value_t::array:
                     {
+
                         // error condition (cf. RFC 6901, Sect. 4)
                         if (reference_token.size() > 1 and reference_token[0] == '0')
                         {
diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp
index 672f15df..11a2c7a2 100644
--- a/test/src/unit-deserialization.cpp
+++ b/test/src/unit-deserialization.cpp
@@ -238,6 +238,18 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
             }
+
+            SECTION("case 3")
+            {
+                uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
+                CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
+            }
+
+            SECTION("case 4")
+            {
+                uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
+                CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
+            }
         }
     }
 }
diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp
index c7f1708c..892a958f 100644
--- a/test/src/unit-json_pointer.cpp
+++ b/test/src/unit-json_pointer.cpp
@@ -109,8 +109,13 @@ TEST_CASE("JSON pointers")
             CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
 
             // unescaped access
-            CHECK_THROWS_AS(j[json::json_pointer("/a/b")], std::out_of_range);
-            CHECK_THROWS_WITH(j[json::json_pointer("/a/b")], "unresolved reference token 'b'");
+            // access to nonexisting values yield object creation
+            CHECK_NOTHROW(j[json::json_pointer("/a/b")] = 42);
+            CHECK(j["a"]["b"] == json(42));
+            CHECK_NOTHROW(j[json::json_pointer("/a/c/1")] = 42);
+            CHECK(j["a"]["c"] == json({nullptr, 42}));
+            CHECK_NOTHROW(j[json::json_pointer("/a/d/-")] = 42);
+            CHECK(j["a"]["d"] == json::array({42}));
             // "/a/b" works for JSON {"a": {"b": 42}}
             CHECK(json({{"a", {{"b", 42}}}})[json::json_pointer("/a/b")] == json(42));
 
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index 34eb197f..6d93e744 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -482,4 +482,11 @@ TEST_CASE("regression tests")
             CHECK_NOTHROW(j << f);
         }
     }
+
+    SECTION("issue #323 - add nested object capabilities to pointers")
+    {
+        json j;
+        j["/this/that"_json_pointer] = 27;
+        CHECK(j == json({{"this", {{"that", 27}}}}));
+    }
 }