diff --git a/src/json.hpp b/src/json.hpp
index db733367..3bba54a6 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -124,6 +124,8 @@ default; will be used in @ref string_t)
 in @ref boolean_t)
 @tparam NumberIntegerType type for JSON integer numbers (@c `int64_t` by
 default; will be used in @ref number_integer_t)
+@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c `uint64_t` by
+default; will be used in @ref number_unsigned_t)
 @tparam NumberFloatType type for JSON floating-point numbers (@c `double` by
 default; will be used in @ref number_float_t)
 @tparam AllocatorType type of the allocator to use (@c `std::allocator` by
@@ -185,6 +187,7 @@ template <
     class StringType = std::string,
     class BooleanType = bool,
     class NumberIntegerType = int64_t,
+    class NumberUnsignedType = uint64_t,
     class NumberFloatType = double,
     template<typename U> class AllocatorType = std::allocator
     >
@@ -197,6 +200,7 @@ class basic_json
           StringType,
           BooleanType,
           NumberIntegerType,
+          NumberUnsignedType,
           NumberFloatType,
           AllocatorType>;
 
@@ -481,9 +485,10 @@ class basic_json
     > permitted.
 
     This description includes both integer and floating-point numbers. However,
-    C++ allows more precise storage if it is known whether the number is an
-    integer or a floating-point number. Therefore, two different types, @ref
-    number_integer_t and @ref number_float_t are used.
+    C++ allows more precise storage if it is known whether the number is a 
+    signed integer, an unsigned integer or a floating-point number. Therefore,
+    three different types, @ref number_integer_t,  @ref number_unsigned_t and 
+    @ref number_float_t are used.
 
     To store integer numbers in C++, a type is defined by the template
     parameter @a NumberIntegerType which chooses the type to use.
@@ -516,7 +521,7 @@ class basic_json
     that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
     that are out of range will yield over/underflow when used in a constructor.
     During deserialization, too large or small integer numbers will be
-    automatically be stored as @ref number_float_t.
+    automatically be stored as @ref number_unsigned_t or @ref number_float_t.
 
     [RFC 7159](http://rfc7159.net/rfc7159) further states:
     > Note that when such software is used, numbers that are integers and are
@@ -532,10 +537,84 @@ class basic_json
 
     @sa @ref number_float_t -- type for number values (floating-point)
 
+    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
+
     @since version 1.0.0
     */
     using number_integer_t = NumberIntegerType;
 
+    /*!
+    @brief a type for a number (unsigned)
+
+    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+    > The representation of numbers is similar to that used in most programming
+    > languages. A number is represented in base 10 using decimal digits. It
+    > contains an integer component that may be prefixed with an optional minus
+    > sign, which may be followed by a fraction part and/or an exponent part.
+    > Leading zeros are not allowed. (...) Numeric values that cannot be
+    > represented in the grammar below (such as Infinity and NaN) are not
+    > permitted.
+
+    This description includes both integer and floating-point numbers. However,
+    C++ allows more precise storage if it is known whether the number is a 
+    signed integer, an unsigned integer or a floating-point number. Therefore,
+    three different types, @ref number_integer_t,  @ref number_unsigned_t and 
+    @ref number_float_t are used.
+
+    To store unsigned integer numbers in C++, a type is defined by the template
+    parameter @a NumberUnsignedType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a NumberUnsignedType (`uint64_t`), the default
+    value for @a number_unsigned_t is:
+
+    @code {.cpp}
+    uint64_t
+    @endcode
+
+    #### Default behavior
+
+    - The restrictions about leading zeros is not enforced in C++. Instead,
+      leading zeros in integer literals lead to an interpretation as octal
+      number. Internally, the value will be stored as decimal number. For
+      instance, the C++ integer literal `010` will be serialized to `8`. During
+      deserialization, leading zeros yield an error.
+    - Not-a-number (NaN) values will be serialized to `null`.
+
+    #### Limits
+
+    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+    > An implementation may set limits on the range and precision of numbers.
+
+    When the default type is used, the maximal integer number that can be
+    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer number
+    that can be stored is `0`. Integer numbers
+    that are out of range will yield over/underflow when used in a constructor.
+    During deserialization, too large or small integer numbers will be
+    automatically be stored as @ref number_integer_t or @ref number_float_t.
+
+    [RFC 7159](http://rfc7159.net/rfc7159) further states:
+    > Note that when such software is used, numbers that are integers and are
+    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+    > that implementations will agree exactly on their numeric values.
+
+    As this range is a subrange (when considered in conjunction with the
+    number_integer_t type) of the exactly supported range [0, UINT64_MAX], this 
+    class's integer type is interoperable.
+
+    #### Storage
+
+    Integer number values are stored directly inside a @ref basic_json type.
+
+    @sa @ref number_float_t -- type for number values (floating-point)
+
+    @sa @ref number_integer_t -- type for number values (integer)
+
+    @since version 2.0.0
+    */
+    using number_unsigned_t = NumberUnsignedType;
+    
     /*!
     @brief a type for a number (floating-point)
 
@@ -549,9 +628,10 @@ class basic_json
     > permitted.
 
     This description includes both integer and floating-point numbers. However,
-    C++ allows more precise storage if it is known whether the number is an
-    integer or a floating-point number. Therefore, two different types, @ref
-    number_integer_t and @ref number_float_t are used.
+    C++ allows more precise storage if it is known whether the number is a 
+    signed integer, an unsigned integer or a floating-point number. Therefore,
+    three different types, @ref number_integer_t,  @ref number_unsigned_t and 
+    @ref number_float_t are used.
 
     To store floating-point numbers in C++, a type is defined by the template
     parameter @a NumberFloatType which chooses the type to use.
@@ -597,6 +677,8 @@ class basic_json
 
     @sa @ref number_integer_t -- type for number values (integer)
 
+    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
+
     @since version 1.0.0
     */
     using number_float_t = NumberFloatType;
@@ -626,6 +708,7 @@ class basic_json
         string,         ///< string value
         boolean,        ///< boolean value
         number_integer, ///< number value (integer)
+        number_unsigned,///< number value (unsigned integer)
         number_float,   ///< number value (floating-point)
         discarded       ///< discarded by the the parser callback function
     };
@@ -669,6 +752,8 @@ class basic_json
         boolean_t boolean;
         /// number (integer)
         number_integer_t number_integer;
+        /// number (unsigned integer)
+        number_unsigned_t number_unsigned;
         /// number (floating-point)
         number_float_t number_float;
 
@@ -678,6 +763,8 @@ class basic_json
         json_value(boolean_t v) noexcept : boolean(v) {}
         /// constructor for numbers (integer)
         json_value(number_integer_t v) noexcept : number_integer(v) {}
+        /// constructor for numbers (unsigned)
+        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
         /// constructor for numbers (floating-point)
         json_value(number_float_t v) noexcept : number_float(v) {}
         /// constructor for empty values of a given type
@@ -714,6 +801,12 @@ class basic_json
                     number_integer = number_integer_t(0);
                     break;
                 }
+                
+                case value_t::number_unsigned:
+                {
+                    number_unsigned = number_unsigned_t(0);
+                    break;
+                }
 
                 case value_t::number_float:
                 {
@@ -870,6 +963,8 @@ class basic_json
     (floating-point) value
     @sa @ref basic_json(const number_integer_t) -- create a number (integer)
     value
+    @sa @ref basic_json(const number_unsigned_t) -- create a number (unsigned)
+    value
 
     @since version 1.0.0
     */
@@ -1171,7 +1266,8 @@ class basic_json
              typename std::enable_if<
                  not (std::is_same<T, int>::value)
                  and std::is_same<T, number_integer_t>::value
-                 , int>::type = 0>
+                 , int>::type
+             = 0>
     basic_json(const number_integer_t val)
         : m_type(value_t::number_integer), m_value(val)
     {}
@@ -1234,13 +1330,74 @@ class basic_json
     template<typename CompatibleNumberIntegerType, typename
              std::enable_if<
                  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
-                 std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
+                 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and 
+                 std::numeric_limits<CompatibleNumberIntegerType>::is_signed, 
+                 CompatibleNumberIntegerType>::type
              = 0>
     basic_json(const CompatibleNumberIntegerType val) noexcept
         : m_type(value_t::number_integer),
           m_value(static_cast<number_integer_t>(val))
     {}
 
+    /*!
+    @brief create an unsigned integer number (explicit)
+
+    Create an unsigned integer number JSON value with a given content.
+
+    @tparam T  helper type to compare number_unsigned_t and unsigned int 
+    (not visible in) the interface.
+
+    @param[in] val  an integer to create a JSON number from
+
+    @complexity Constant.
+
+    @sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number
+    value (unsigned integer) from a compatible number type
+
+    @since version 2.0.0
+    */
+    template<typename T,
+             typename std::enable_if<
+                 not (std::is_same<T, int>::value)
+                 and std::is_same<T, number_unsigned_t>::value
+                 , int>::type
+             = 0>
+    basic_json(const number_unsigned_t val)
+        : m_type(value_t::number_unsigned), m_value(val)
+    {}
+    
+    /*!
+    @brief create an unsigned number (implicit)
+
+    Create an unsigned number JSON value with a given content. This constructor
+    allows any type that can be used to construct values of type @ref
+    number_unsigned_t. Examples may include the types `unsigned int`, `uint32_t`,
+    or `unsigned short`.
+
+    @tparam CompatibleNumberUnsignedType an integer type which is compatible to
+    @ref number_unsigned_t.
+
+    @param[in] val  an unsigned integer to create a JSON number from
+
+    @complexity Constant.
+
+    @sa @ref basic_json(const number_unsigned_t) -- create a number value
+    (unsigned)
+
+    @since version 2.0.0
+    */
+    template<typename CompatibleNumberUnsignedType, typename
+             std::enable_if<
+                 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
+                 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and 
+                 !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, 
+                 CompatibleNumberUnsignedType>::type
+             = 0>
+    basic_json(const CompatibleNumberUnsignedType val) noexcept
+        : m_type(value_t::number_unsigned),
+          m_value(static_cast<number_unsigned_t>(val))
+    {}
+
     /*!
     @brief create a floating-point number (explicit)
 
@@ -1600,6 +1757,7 @@ class basic_json
             case value_t::boolean:
             case value_t::number_float:
             case value_t::number_integer:
+            case value_t::number_unsigned:
             case value_t::string:
             {
                 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
@@ -1623,6 +1781,13 @@ class basic_json
                 m_value.number_integer = first.m_object->m_value.number_integer;
                 break;
             }
+            
+            case value_t::number_unsigned:
+            {
+                assert(first.m_object != nullptr);
+                m_value.number_unsigned = first.m_object->m_value.number_unsigned;
+                break;
+            }
 
             case value_t::number_float:
             {
@@ -1726,6 +1891,12 @@ class basic_json
                 m_value = other.m_value.number_integer;
                 break;
             }
+            
+            case value_t::number_unsigned:
+            {
+                m_value = other.m_value.number_unsigned;
+                break;
+            }
 
             case value_t::number_float:
             {
@@ -2004,15 +2175,17 @@ class basic_json
     This function returns true iff the JSON value is a number. This includes
     both integer and floating-point values.
 
-    @return `true` if type is number (regardless whether integer or
-    floating-type), `false` otherwise.
+    @return `true` if type is number (regardless whether integer, unsigned
+    integer or floating-type), `false` otherwise.
 
     @complexity Constant.
 
     @liveexample{The following code exemplifies @ref is_number for all JSON
     types.,is_number}
 
-    @sa @ref is_number_integer() -- check if value is an integer number
+    @sa @ref is_number_integer() -- check if value is an integer or unsigned 
+    integer number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer number
     @sa @ref is_number_float() -- check if value is a floating-point number
 
     @since version 1.0.0
@@ -2025,10 +2198,11 @@ class basic_json
     /*!
     @brief return whether value is an integer number
 
-    This function returns true iff the JSON value is an integer number. This
-    excludes floating-point values.
+    This function returns true iff the JSON value is an integer or unsigned 
+    integer number. This excludes floating-point values.
 
-    @return `true` if type is an integer number, `false` otherwise.
+    @return `true` if type is an integer or unsigned integer number, `false` 
+    otherwise.
 
     @complexity Constant.
 
@@ -2036,20 +2210,43 @@ class basic_json
     JSON types.,is_number_integer}
 
     @sa @ref is_number() -- check if value is a number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer number
     @sa @ref is_number_float() -- check if value is a floating-point number
 
     @since version 1.0.0
     */
     bool is_number_integer() const noexcept
     {
-        return m_type == value_t::number_integer;
+        return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
+    }
+    
+    /*!
+    @brief return whether value is an unsigned integer number
+
+    This function returns true iff the JSON value is an unsigned integer number. 
+    This excludes floating-point and (signed) integer values.
+
+    @return `true` if type is an unsigned integer number, `false` otherwise.
+
+    @complexity Constant.
+
+    @sa @ref is_number() -- check if value is a number
+    @sa @ref is_number_integer() -- check if value is an integer or unsigned 
+    integer number
+    @sa @ref is_number_float() -- check if value is a floating-point number
+
+    @since version 2.0.0
+    */
+    bool is_number_unsigned() const noexcept
+    {
+        return m_type == value_t::number_unsigned;
     }
 
     /*!
     @brief return whether value is a floating-point number
 
     This function returns true iff the JSON value is a floating-point number.
-    This excludes integer values.
+    This excludes integer and unsigned integer values.
 
     @return `true` if type is a floating-point number, `false` otherwise.
 
@@ -2060,6 +2257,7 @@ class basic_json
 
     @sa @ref is_number() -- check if value is number
     @sa @ref is_number_integer() -- check if value is an integer number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer number
 
     @since version 1.0.0
     */
@@ -2327,6 +2525,11 @@ class basic_json
             {
                 return static_cast<T>(m_value.number_integer);
             }
+            
+            case value_t::number_unsigned:
+            {
+                return static_cast<T>(m_value.number_unsigned);
+            }
 
             case value_t::number_float:
             {
@@ -2412,7 +2615,19 @@ class basic_json
     {
         return is_number_integer() ? &m_value.number_integer : nullptr;
     }
+    
+    /// get a pointer to the value (unsigned number)
+    number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
 
+    /// get a pointer to the value (unsigned number)
+    const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
+    
     /// get a pointer to the value (floating-point number)
     number_float_t* get_impl_ptr(number_float_t*) noexcept
     {
@@ -2510,8 +2725,8 @@ class basic_json
     @warning The pointer becomes invalid if the underlying JSON object changes.
 
     @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.
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 
+    @ref number_unsigned_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
@@ -2561,8 +2776,8 @@ class basic_json
     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.
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 
+    @ref number_unsigned_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
@@ -2680,14 +2895,14 @@ class basic_json
 
     @since version 1.0.0
     */
-    template < typename ValueType, typename
-               std::enable_if <
-                   not std::is_pointer<ValueType>::value
-                   and not std::is_same<ValueType, typename string_t::value_type>::value
+    template<typename ValueType, typename
+             std::enable_if<
+                 not std::is_pointer<ValueType>::value
+                 and not std::is_same<ValueType, typename string_t::value_type>::value
 #ifndef _MSC_VER  // Fix for issue #167 operator<< abiguity under VS2015
-                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
+                 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
 #endif
-                   , int >::type = 0 >
+                 , int>::type = 0>
     operator ValueType() const
     {
         // delegate the call to get<>() const
@@ -3441,6 +3656,7 @@ class basic_json
             case value_t::boolean:
             case value_t::number_float:
             case value_t::number_integer:
+            case value_t::number_unsigned:
             case value_t::string:
             {
                 if (not pos.m_it.primitive_iterator.is_begin())
@@ -3546,6 +3762,7 @@ class basic_json
             case value_t::boolean:
             case value_t::number_float:
             case value_t::number_integer:
+            case value_t::number_unsigned:
             case value_t::string:
             {
                 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
@@ -4235,6 +4452,12 @@ class basic_json
                 break;
             }
 
+            case value_t::number_unsigned:
+            {
+                m_value.number_unsigned = 0;
+                break;
+            }
+
             case value_t::number_float:
             {
                 m_value.number_float = 0.0;
@@ -4773,14 +4996,15 @@ class basic_json
     */
     friend bool operator<(const value_t lhs, const value_t rhs)
     {
-        static constexpr std::array<uint8_t, 7> order = {{
+        static constexpr std::array<uint8_t, 8> order = {{
                 0, // null
                 3, // object
                 4, // array
                 5, // string
                 1, // boolean
                 2, // integer
-                2  // float
+                2, // unsigned
+                2, // float
             }
         };
 
@@ -4856,6 +5080,10 @@ class basic_json
                 {
                     return lhs.m_value.number_integer == rhs.m_value.number_integer;
                 }
+                case value_t::number_unsigned:
+                {
+                    return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
+                }
                 case value_t::number_float:
                 {
                     return lhs.m_value.number_float == rhs.m_value.number_float;
@@ -4874,6 +5102,23 @@ class basic_json
         {
             return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
         }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
+        {
+            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
+        }
+        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+        }
+
         return false;
     }
 
@@ -5025,6 +5270,10 @@ class basic_json
                 {
                     return lhs.m_value.number_integer < rhs.m_value.number_integer;
                 }
+                case value_t::number_unsigned:
+                {
+                    return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
+                }
                 case value_t::number_float:
                 {
                     return lhs.m_value.number_float < rhs.m_value.number_float;
@@ -5037,13 +5286,27 @@ class basic_json
         }
         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
         {
-            return static_cast<number_float_t>(lhs.m_value.number_integer) <
-                   rhs.m_value.number_float;
+            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
         }
         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
         {
-            return lhs.m_value.number_float <
-                   static_cast<number_float_t>(rhs.m_value.number_integer);
+            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
+        {
+            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
         }
 
         // We only reach this line if we cannot compare values. In that case,
@@ -5608,6 +5871,12 @@ class basic_json
                 return;
             }
 
+            case value_t::number_unsigned:
+            {
+                o << m_value.number_unsigned;
+                return;
+            }
+
             case value_t::number_float:
             {
                 // If the number is an integer then output as a fixed with with
@@ -6831,789 +7100,386 @@ class basic_json
             m_start = m_cursor;
             assert(m_start != nullptr);
 
-
-            {
-                lexer_char_t yych;
-                unsigned int yyaccept = 0;
-                static const unsigned char yybm[] =
-                {
-                    0,   0,   0,   0,   0,   0,   0,   0,
-                    0,  32,  32,   0,   0,  32,   0,   0,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    96,  64,   0,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    192, 192, 192, 192, 192, 192, 192, 192,
-                    192, 192,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,   0,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                    64,  64,  64,  64,  64,  64,  64,  64,
-                };
-                if ((m_limit - m_cursor) < 5)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
+            
+    {
+        lexer_char_t yych;
+        unsigned int yyaccept = 0;
+        static const unsigned char yybm[] = {
+              0,   0,   0,   0,   0,   0,   0,   0, 
+              0,  32,  32,   0,   0,  32,   0,   0, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             96,  64,   0,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+            192, 192, 192, 192, 192, 192, 192, 192, 
+            192, 192,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,   0,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+             64,  64,  64,  64,  64,  64,  64,  64, 
+        };
+        if ((m_limit - m_cursor) < 5) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+        if (yych <= ':') {
+            if (yych <= ' ') {
+                if (yych <= '\n') {
+                    if (yych <= 0x00) goto basic_json_parser_28;
+                    if (yych <= 0x08) goto basic_json_parser_30;
+                    if (yych >= '\n') goto basic_json_parser_4;
+                } else {
+                    if (yych == '\r') goto basic_json_parser_2;
+                    if (yych <= 0x1F) goto basic_json_parser_30;
                 }
-                yych = *m_cursor;
-                if (yych <= ':')
-                {
-                    if (yych <= ' ')
-                    {
-                        if (yych <= '\n')
-                        {
-                            if (yych <= 0x00)
-                            {
-                                goto basic_json_parser_28;
-                            }
-                            if (yych <= 0x08)
-                            {
-                                goto basic_json_parser_30;
-                            }
-                            if (yych >= '\n')
-                            {
-                                goto basic_json_parser_4;
-                            }
-                        }
-                        else
-                        {
-                            if (yych == '\r')
-                            {
-                                goto basic_json_parser_2;
-                            }
-                            if (yych <= 0x1F)
-                            {
-                                goto basic_json_parser_30;
-                            }
-                        }
+            } else {
+                if (yych <= ',') {
+                    if (yych == '"') goto basic_json_parser_27;
+                    if (yych <= '+') goto basic_json_parser_30;
+                    goto basic_json_parser_16;
+                } else {
+                    if (yych <= '/') {
+                        if (yych <= '-') goto basic_json_parser_23;
+                        goto basic_json_parser_30;
+                    } else {
+                        if (yych <= '0') goto basic_json_parser_24;
+                        if (yych <= '9') goto basic_json_parser_26;
+                        goto basic_json_parser_18;
                     }
-                    else
-                    {
-                        if (yych <= ',')
-                        {
-                            if (yych == '"')
-                            {
-                                goto basic_json_parser_27;
-                            }
-                            if (yych <= '+')
-                            {
-                                goto basic_json_parser_30;
-                            }
-                            goto basic_json_parser_16;
-                        }
-                        else
-                        {
-                            if (yych <= '/')
-                            {
-                                if (yych <= '-')
-                                {
-                                    goto basic_json_parser_23;
-                                }
-                                goto basic_json_parser_30;
-                            }
-                            else
-                            {
-                                if (yych <= '0')
-                                {
-                                    goto basic_json_parser_24;
-                                }
-                                if (yych <= '9')
-                                {
-                                    goto basic_json_parser_26;
-                                }
-                                goto basic_json_parser_18;
-                            }
-                        }
-                    }
-                }
-                else
-                {
-                    if (yych <= 'n')
-                    {
-                        if (yych <= ']')
-                        {
-                            if (yych == '[')
-                            {
-                                goto basic_json_parser_8;
-                            }
-                            if (yych <= '\\')
-                            {
-                                goto basic_json_parser_30;
-                            }
-                            goto basic_json_parser_10;
-                        }
-                        else
-                        {
-                            if (yych == 'f')
-                            {
-                                goto basic_json_parser_22;
-                            }
-                            if (yych <= 'm')
-                            {
-                                goto basic_json_parser_30;
-                            }
-                            goto basic_json_parser_20;
-                        }
-                    }
-                    else
-                    {
-                        if (yych <= '{')
-                        {
-                            if (yych == 't')
-                            {
-                                goto basic_json_parser_21;
-                            }
-                            if (yych <= 'z')
-                            {
-                                goto basic_json_parser_30;
-                            }
-                            goto basic_json_parser_12;
-                        }
-                        else
-                        {
-                            if (yych <= '}')
-                            {
-                                if (yych <= '|')
-                                {
-                                    goto basic_json_parser_30;
-                                }
-                                goto basic_json_parser_14;
-                            }
-                            else
-                            {
-                                if (yych == 0xEF)
-                                {
-                                    goto basic_json_parser_6;
-                                }
-                                goto basic_json_parser_30;
-                            }
-                        }
-                    }
-                }
-basic_json_parser_2:
-                ++m_cursor;
-                yych = *m_cursor;
-                goto basic_json_parser_5;
-basic_json_parser_3:
-                {
-                    return scan();
-                }
-basic_json_parser_4:
-                ++m_cursor;
-                if (m_limit <= m_cursor)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-basic_json_parser_5:
-                if (yybm[0 + yych] & 32)
-                {
-                    goto basic_json_parser_4;
-                }
-                goto basic_json_parser_3;
-basic_json_parser_6:
-                yyaccept = 0;
-                yych = *(m_marker = ++m_cursor);
-                if (yych == 0xBB)
-                {
-                    goto basic_json_parser_64;
-                }
-basic_json_parser_7:
-                {
-                    return token_type::parse_error;
-                }
-basic_json_parser_8:
-                ++m_cursor;
-                {
-                    return token_type::begin_array;
-                }
-basic_json_parser_10:
-                ++m_cursor;
-                {
-                    return token_type::end_array;
-                }
-basic_json_parser_12:
-                ++m_cursor;
-                {
-                    return token_type::begin_object;
-                }
-basic_json_parser_14:
-                ++m_cursor;
-                {
-                    return token_type::end_object;
-                }
-basic_json_parser_16:
-                ++m_cursor;
-                {
-                    return token_type::value_separator;
-                }
-basic_json_parser_18:
-                ++m_cursor;
-                {
-                    return token_type::name_separator;
-                }
-basic_json_parser_20:
-                yyaccept = 0;
-                yych = *(m_marker = ++m_cursor);
-                if (yych == 'u')
-                {
-                    goto basic_json_parser_60;
-                }
-                goto basic_json_parser_7;
-basic_json_parser_21:
-                yyaccept = 0;
-                yych = *(m_marker = ++m_cursor);
-                if (yych == 'r')
-                {
-                    goto basic_json_parser_56;
-                }
-                goto basic_json_parser_7;
-basic_json_parser_22:
-                yyaccept = 0;
-                yych = *(m_marker = ++m_cursor);
-                if (yych == 'a')
-                {
-                    goto basic_json_parser_51;
-                }
-                goto basic_json_parser_7;
-basic_json_parser_23:
-                yych = *++m_cursor;
-                if (yych <= '/')
-                {
-                    goto basic_json_parser_7;
-                }
-                if (yych <= '0')
-                {
-                    goto basic_json_parser_50;
-                }
-                if (yych <= '9')
-                {
-                    goto basic_json_parser_41;
-                }
-                goto basic_json_parser_7;
-basic_json_parser_24:
-                yyaccept = 1;
-                yych = *(m_marker = ++m_cursor);
-                if (yych <= 'D')
-                {
-                    if (yych == '.')
-                    {
-                        goto basic_json_parser_43;
-                    }
-                }
-                else
-                {
-                    if (yych <= 'E')
-                    {
-                        goto basic_json_parser_44;
-                    }
-                    if (yych == 'e')
-                    {
-                        goto basic_json_parser_44;
-                    }
-                }
-basic_json_parser_25:
-                {
-                    return token_type::value_number;
-                }
-basic_json_parser_26:
-                yyaccept = 1;
-                yych = *(m_marker = ++m_cursor);
-                goto basic_json_parser_42;
-basic_json_parser_27:
-                yyaccept = 0;
-                yych = *(m_marker = ++m_cursor);
-                if (yych <= 0x0F)
-                {
-                    goto basic_json_parser_7;
-                }
-                goto basic_json_parser_32;
-basic_json_parser_28:
-                ++m_cursor;
-                {
-                    return token_type::end_of_input;
-                }
-basic_json_parser_30:
-                yych = *++m_cursor;
-                goto basic_json_parser_7;
-basic_json_parser_31:
-                ++m_cursor;
-                if (m_limit <= m_cursor)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-basic_json_parser_32:
-                if (yybm[0 + yych] & 64)
-                {
-                    goto basic_json_parser_31;
-                }
-                if (yych <= 0x0F)
-                {
-                    goto basic_json_parser_33;
-                }
-                if (yych <= '"')
-                {
-                    goto basic_json_parser_35;
-                }
-                goto basic_json_parser_34;
-basic_json_parser_33:
-                m_cursor = m_marker;
-                if (yyaccept == 0)
-                {
-                    goto basic_json_parser_7;
-                }
-                else
-                {
-                    goto basic_json_parser_25;
-                }
-basic_json_parser_34:
-                ++m_cursor;
-                if (m_limit <= m_cursor)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-                if (yych <= 'e')
-                {
-                    if (yych <= '/')
-                    {
-                        if (yych == '"')
-                        {
-                            goto basic_json_parser_31;
-                        }
-                        if (yych <= '.')
-                        {
-                            goto basic_json_parser_33;
-                        }
-                        goto basic_json_parser_31;
-                    }
-                    else
-                    {
-                        if (yych <= '\\')
-                        {
-                            if (yych <= '[')
-                            {
-                                goto basic_json_parser_33;
-                            }
-                            goto basic_json_parser_31;
-                        }
-                        else
-                        {
-                            if (yych == 'b')
-                            {
-                                goto basic_json_parser_31;
-                            }
-                            goto basic_json_parser_33;
-                        }
-                    }
-                }
-                else
-                {
-                    if (yych <= 'q')
-                    {
-                        if (yych <= 'f')
-                        {
-                            goto basic_json_parser_31;
-                        }
-                        if (yych == 'n')
-                        {
-                            goto basic_json_parser_31;
-                        }
-                        goto basic_json_parser_33;
-                    }
-                    else
-                    {
-                        if (yych <= 's')
-                        {
-                            if (yych <= 'r')
-                            {
-                                goto basic_json_parser_31;
-                            }
-                            goto basic_json_parser_33;
-                        }
-                        else
-                        {
-                            if (yych <= 't')
-                            {
-                                goto basic_json_parser_31;
-                            }
-                            if (yych <= 'u')
-                            {
-                                goto basic_json_parser_37;
-                            }
-                            goto basic_json_parser_33;
-                        }
-                    }
-                }
-basic_json_parser_35:
-                ++m_cursor;
-                {
-                    return token_type::value_string;
-                }
-basic_json_parser_37:
-                ++m_cursor;
-                if (m_limit <= m_cursor)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-                if (yych <= '@')
-                {
-                    if (yych <= '/')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych >= ':')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                }
-                else
-                {
-                    if (yych <= 'F')
-                    {
-                        goto basic_json_parser_38;
-                    }
-                    if (yych <= '`')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych >= 'g')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                }
-basic_json_parser_38:
-                ++m_cursor;
-                if (m_limit <= m_cursor)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-                if (yych <= '@')
-                {
-                    if (yych <= '/')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych >= ':')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                }
-                else
-                {
-                    if (yych <= 'F')
-                    {
-                        goto basic_json_parser_39;
-                    }
-                    if (yych <= '`')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych >= 'g')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                }
-basic_json_parser_39:
-                ++m_cursor;
-                if (m_limit <= m_cursor)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-                if (yych <= '@')
-                {
-                    if (yych <= '/')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych >= ':')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                }
-                else
-                {
-                    if (yych <= 'F')
-                    {
-                        goto basic_json_parser_40;
-                    }
-                    if (yych <= '`')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych >= 'g')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                }
-basic_json_parser_40:
-                ++m_cursor;
-                if (m_limit <= m_cursor)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-                if (yych <= '@')
-                {
-                    if (yych <= '/')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych <= '9')
-                    {
-                        goto basic_json_parser_31;
-                    }
-                    goto basic_json_parser_33;
-                }
-                else
-                {
-                    if (yych <= 'F')
-                    {
-                        goto basic_json_parser_31;
-                    }
-                    if (yych <= '`')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych <= 'f')
-                    {
-                        goto basic_json_parser_31;
-                    }
-                    goto basic_json_parser_33;
-                }
-basic_json_parser_41:
-                yyaccept = 1;
-                m_marker = ++m_cursor;
-                if ((m_limit - m_cursor) < 3)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-basic_json_parser_42:
-                if (yybm[0 + yych] & 128)
-                {
-                    goto basic_json_parser_41;
-                }
-                if (yych <= 'D')
-                {
-                    if (yych != '.')
-                    {
-                        goto basic_json_parser_25;
-                    }
-                }
-                else
-                {
-                    if (yych <= 'E')
-                    {
-                        goto basic_json_parser_44;
-                    }
-                    if (yych == 'e')
-                    {
-                        goto basic_json_parser_44;
-                    }
-                    goto basic_json_parser_25;
-                }
-basic_json_parser_43:
-                yych = *++m_cursor;
-                if (yych <= '/')
-                {
-                    goto basic_json_parser_33;
-                }
-                if (yych <= '9')
-                {
-                    goto basic_json_parser_48;
-                }
-                goto basic_json_parser_33;
-basic_json_parser_44:
-                yych = *++m_cursor;
-                if (yych <= ',')
-                {
-                    if (yych != '+')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                }
-                else
-                {
-                    if (yych <= '-')
-                    {
-                        goto basic_json_parser_45;
-                    }
-                    if (yych <= '/')
-                    {
-                        goto basic_json_parser_33;
-                    }
-                    if (yych <= '9')
-                    {
-                        goto basic_json_parser_46;
-                    }
-                    goto basic_json_parser_33;
-                }
-basic_json_parser_45:
-                yych = *++m_cursor;
-                if (yych <= '/')
-                {
-                    goto basic_json_parser_33;
-                }
-                if (yych >= ':')
-                {
-                    goto basic_json_parser_33;
-                }
-basic_json_parser_46:
-                ++m_cursor;
-                if (m_limit <= m_cursor)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-                if (yych <= '/')
-                {
-                    goto basic_json_parser_25;
-                }
-                if (yych <= '9')
-                {
-                    goto basic_json_parser_46;
-                }
-                goto basic_json_parser_25;
-basic_json_parser_48:
-                yyaccept = 1;
-                m_marker = ++m_cursor;
-                if ((m_limit - m_cursor) < 3)
-                {
-                    yyfill();    // LCOV_EXCL_LINE;
-                }
-                yych = *m_cursor;
-                if (yych <= 'D')
-                {
-                    if (yych <= '/')
-                    {
-                        goto basic_json_parser_25;
-                    }
-                    if (yych <= '9')
-                    {
-                        goto basic_json_parser_48;
-                    }
-                    goto basic_json_parser_25;
-                }
-                else
-                {
-                    if (yych <= 'E')
-                    {
-                        goto basic_json_parser_44;
-                    }
-                    if (yych == 'e')
-                    {
-                        goto basic_json_parser_44;
-                    }
-                    goto basic_json_parser_25;
-                }
-basic_json_parser_50:
-                yyaccept = 1;
-                yych = *(m_marker = ++m_cursor);
-                if (yych <= 'D')
-                {
-                    if (yych == '.')
-                    {
-                        goto basic_json_parser_43;
-                    }
-                    goto basic_json_parser_25;
-                }
-                else
-                {
-                    if (yych <= 'E')
-                    {
-                        goto basic_json_parser_44;
-                    }
-                    if (yych == 'e')
-                    {
-                        goto basic_json_parser_44;
-                    }
-                    goto basic_json_parser_25;
-                }
-basic_json_parser_51:
-                yych = *++m_cursor;
-                if (yych != 'l')
-                {
-                    goto basic_json_parser_33;
-                }
-                yych = *++m_cursor;
-                if (yych != 's')
-                {
-                    goto basic_json_parser_33;
-                }
-                yych = *++m_cursor;
-                if (yych != 'e')
-                {
-                    goto basic_json_parser_33;
-                }
-                ++m_cursor;
-                {
-                    return token_type::literal_false;
-                }
-basic_json_parser_56:
-                yych = *++m_cursor;
-                if (yych != 'u')
-                {
-                    goto basic_json_parser_33;
-                }
-                yych = *++m_cursor;
-                if (yych != 'e')
-                {
-                    goto basic_json_parser_33;
-                }
-                ++m_cursor;
-                {
-                    return token_type::literal_true;
-                }
-basic_json_parser_60:
-                yych = *++m_cursor;
-                if (yych != 'l')
-                {
-                    goto basic_json_parser_33;
-                }
-                yych = *++m_cursor;
-                if (yych != 'l')
-                {
-                    goto basic_json_parser_33;
-                }
-                ++m_cursor;
-                {
-                    return token_type::literal_null;
-                }
-basic_json_parser_64:
-                yych = *++m_cursor;
-                if (yych != 0xBF)
-                {
-                    goto basic_json_parser_33;
-                }
-                ++m_cursor;
-                {
-                    return scan();
                 }
             }
+        } else {
+            if (yych <= 'n') {
+                if (yych <= ']') {
+                    if (yych == '[') goto basic_json_parser_8;
+                    if (yych <= '\\') goto basic_json_parser_30;
+                    goto basic_json_parser_10;
+                } else {
+                    if (yych == 'f') goto basic_json_parser_22;
+                    if (yych <= 'm') goto basic_json_parser_30;
+                    goto basic_json_parser_20;
+                }
+            } else {
+                if (yych <= '{') {
+                    if (yych == 't') goto basic_json_parser_21;
+                    if (yych <= 'z') goto basic_json_parser_30;
+                    goto basic_json_parser_12;
+                } else {
+                    if (yych <= '}') {
+                        if (yych <= '|') goto basic_json_parser_30;
+                        goto basic_json_parser_14;
+                    } else {
+                        if (yych == 0xEF) goto basic_json_parser_6;
+                        goto basic_json_parser_30;
+                    }
+                }
+            }
+        }
+basic_json_parser_2:
+        ++m_cursor;
+        yych = *m_cursor;
+        goto basic_json_parser_5;
+basic_json_parser_3:
+        { return scan(); }
+basic_json_parser_4:
+        ++m_cursor;
+        if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+basic_json_parser_5:
+        if (yybm[0+yych] & 32) {
+            goto basic_json_parser_4;
+        }
+        goto basic_json_parser_3;
+basic_json_parser_6:
+        yyaccept = 0;
+        yych = *(m_marker = ++m_cursor);
+        if (yych == 0xBB) goto basic_json_parser_64;
+basic_json_parser_7:
+        { return token_type::parse_error; }
+basic_json_parser_8:
+        ++m_cursor;
+        { return token_type::begin_array; }
+basic_json_parser_10:
+        ++m_cursor;
+        { return token_type::end_array; }
+basic_json_parser_12:
+        ++m_cursor;
+        { return token_type::begin_object; }
+basic_json_parser_14:
+        ++m_cursor;
+        { return token_type::end_object; }
+basic_json_parser_16:
+        ++m_cursor;
+        { return token_type::value_separator; }
+basic_json_parser_18:
+        ++m_cursor;
+        { return token_type::name_separator; }
+basic_json_parser_20:
+        yyaccept = 0;
+        yych = *(m_marker = ++m_cursor);
+        if (yych == 'u') goto basic_json_parser_60;
+        goto basic_json_parser_7;
+basic_json_parser_21:
+        yyaccept = 0;
+        yych = *(m_marker = ++m_cursor);
+        if (yych == 'r') goto basic_json_parser_56;
+        goto basic_json_parser_7;
+basic_json_parser_22:
+        yyaccept = 0;
+        yych = *(m_marker = ++m_cursor);
+        if (yych == 'a') goto basic_json_parser_51;
+        goto basic_json_parser_7;
+basic_json_parser_23:
+        yych = *++m_cursor;
+        if (yych <= '/') goto basic_json_parser_7;
+        if (yych <= '0') goto basic_json_parser_50;
+        if (yych <= '9') goto basic_json_parser_41;
+        goto basic_json_parser_7;
+basic_json_parser_24:
+        yyaccept = 1;
+        yych = *(m_marker = ++m_cursor);
+        if (yych <= 'D') {
+            if (yych == '.') goto basic_json_parser_43;
+        } else {
+            if (yych <= 'E') goto basic_json_parser_44;
+            if (yych == 'e') goto basic_json_parser_44;
+        }
+basic_json_parser_25:
+        { return token_type::value_number; }
+basic_json_parser_26:
+        yyaccept = 1;
+        yych = *(m_marker = ++m_cursor);
+        goto basic_json_parser_42;
+basic_json_parser_27:
+        yyaccept = 0;
+        yych = *(m_marker = ++m_cursor);
+        if (yych <= 0x0F) goto basic_json_parser_7;
+        goto basic_json_parser_32;
+basic_json_parser_28:
+        ++m_cursor;
+        { return token_type::end_of_input; }
+basic_json_parser_30:
+        yych = *++m_cursor;
+        goto basic_json_parser_7;
+basic_json_parser_31:
+        ++m_cursor;
+        if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+basic_json_parser_32:
+        if (yybm[0+yych] & 64) {
+            goto basic_json_parser_31;
+        }
+        if (yych <= 0x0F) goto basic_json_parser_33;
+        if (yych <= '"') goto basic_json_parser_35;
+        goto basic_json_parser_34;
+basic_json_parser_33:
+        m_cursor = m_marker;
+        if (yyaccept == 0) {
+            goto basic_json_parser_7;
+        } else {
+            goto basic_json_parser_25;
+        }
+basic_json_parser_34:
+        ++m_cursor;
+        if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+        if (yych <= 'e') {
+            if (yych <= '/') {
+                if (yych == '"') goto basic_json_parser_31;
+                if (yych <= '.') goto basic_json_parser_33;
+                goto basic_json_parser_31;
+            } else {
+                if (yych <= '\\') {
+                    if (yych <= '[') goto basic_json_parser_33;
+                    goto basic_json_parser_31;
+                } else {
+                    if (yych == 'b') goto basic_json_parser_31;
+                    goto basic_json_parser_33;
+                }
+            }
+        } else {
+            if (yych <= 'q') {
+                if (yych <= 'f') goto basic_json_parser_31;
+                if (yych == 'n') goto basic_json_parser_31;
+                goto basic_json_parser_33;
+            } else {
+                if (yych <= 's') {
+                    if (yych <= 'r') goto basic_json_parser_31;
+                    goto basic_json_parser_33;
+                } else {
+                    if (yych <= 't') goto basic_json_parser_31;
+                    if (yych <= 'u') goto basic_json_parser_37;
+                    goto basic_json_parser_33;
+                }
+            }
+        }
+basic_json_parser_35:
+        ++m_cursor;
+        { return token_type::value_string; }
+basic_json_parser_37:
+        ++m_cursor;
+        if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+        if (yych <= '@') {
+            if (yych <= '/') goto basic_json_parser_33;
+            if (yych >= ':') goto basic_json_parser_33;
+        } else {
+            if (yych <= 'F') goto basic_json_parser_38;
+            if (yych <= '`') goto basic_json_parser_33;
+            if (yych >= 'g') goto basic_json_parser_33;
+        }
+basic_json_parser_38:
+        ++m_cursor;
+        if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+        if (yych <= '@') {
+            if (yych <= '/') goto basic_json_parser_33;
+            if (yych >= ':') goto basic_json_parser_33;
+        } else {
+            if (yych <= 'F') goto basic_json_parser_39;
+            if (yych <= '`') goto basic_json_parser_33;
+            if (yych >= 'g') goto basic_json_parser_33;
+        }
+basic_json_parser_39:
+        ++m_cursor;
+        if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+        if (yych <= '@') {
+            if (yych <= '/') goto basic_json_parser_33;
+            if (yych >= ':') goto basic_json_parser_33;
+        } else {
+            if (yych <= 'F') goto basic_json_parser_40;
+            if (yych <= '`') goto basic_json_parser_33;
+            if (yych >= 'g') goto basic_json_parser_33;
+        }
+basic_json_parser_40:
+        ++m_cursor;
+        if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+        if (yych <= '@') {
+            if (yych <= '/') goto basic_json_parser_33;
+            if (yych <= '9') goto basic_json_parser_31;
+            goto basic_json_parser_33;
+        } else {
+            if (yych <= 'F') goto basic_json_parser_31;
+            if (yych <= '`') goto basic_json_parser_33;
+            if (yych <= 'f') goto basic_json_parser_31;
+            goto basic_json_parser_33;
+        }
+basic_json_parser_41:
+        yyaccept = 1;
+        m_marker = ++m_cursor;
+        if ((m_limit - m_cursor) < 3) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+basic_json_parser_42:
+        if (yybm[0+yych] & 128) {
+            goto basic_json_parser_41;
+        }
+        if (yych <= 'D') {
+            if (yych != '.') goto basic_json_parser_25;
+        } else {
+            if (yych <= 'E') goto basic_json_parser_44;
+            if (yych == 'e') goto basic_json_parser_44;
+            goto basic_json_parser_25;
+        }
+basic_json_parser_43:
+        yych = *++m_cursor;
+        if (yych <= '/') goto basic_json_parser_33;
+        if (yych <= '9') goto basic_json_parser_48;
+        goto basic_json_parser_33;
+basic_json_parser_44:
+        yych = *++m_cursor;
+        if (yych <= ',') {
+            if (yych != '+') goto basic_json_parser_33;
+        } else {
+            if (yych <= '-') goto basic_json_parser_45;
+            if (yych <= '/') goto basic_json_parser_33;
+            if (yych <= '9') goto basic_json_parser_46;
+            goto basic_json_parser_33;
+        }
+basic_json_parser_45:
+        yych = *++m_cursor;
+        if (yych <= '/') goto basic_json_parser_33;
+        if (yych >= ':') goto basic_json_parser_33;
+basic_json_parser_46:
+        ++m_cursor;
+        if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+        if (yych <= '/') goto basic_json_parser_25;
+        if (yych <= '9') goto basic_json_parser_46;
+        goto basic_json_parser_25;
+basic_json_parser_48:
+        yyaccept = 1;
+        m_marker = ++m_cursor;
+        if ((m_limit - m_cursor) < 3) yyfill(); // LCOV_EXCL_LINE;
+        yych = *m_cursor;
+        if (yych <= 'D') {
+            if (yych <= '/') goto basic_json_parser_25;
+            if (yych <= '9') goto basic_json_parser_48;
+            goto basic_json_parser_25;
+        } else {
+            if (yych <= 'E') goto basic_json_parser_44;
+            if (yych == 'e') goto basic_json_parser_44;
+            goto basic_json_parser_25;
+        }
+basic_json_parser_50:
+        yyaccept = 1;
+        yych = *(m_marker = ++m_cursor);
+        if (yych <= 'D') {
+            if (yych == '.') goto basic_json_parser_43;
+            goto basic_json_parser_25;
+        } else {
+            if (yych <= 'E') goto basic_json_parser_44;
+            if (yych == 'e') goto basic_json_parser_44;
+            goto basic_json_parser_25;
+        }
+basic_json_parser_51:
+        yych = *++m_cursor;
+        if (yych != 'l') goto basic_json_parser_33;
+        yych = *++m_cursor;
+        if (yych != 's') goto basic_json_parser_33;
+        yych = *++m_cursor;
+        if (yych != 'e') goto basic_json_parser_33;
+        ++m_cursor;
+        { return token_type::literal_false; }
+basic_json_parser_56:
+        yych = *++m_cursor;
+        if (yych != 'u') goto basic_json_parser_33;
+        yych = *++m_cursor;
+        if (yych != 'e') goto basic_json_parser_33;
+        ++m_cursor;
+        { return token_type::literal_true; }
+basic_json_parser_60:
+        yych = *++m_cursor;
+        if (yych != 'l') goto basic_json_parser_33;
+        yych = *++m_cursor;
+        if (yych != 'l') goto basic_json_parser_33;
+        ++m_cursor;
+        { return token_type::literal_null; }
+basic_json_parser_64:
+        yych = *++m_cursor;
+        if (yych != 0xBF) goto basic_json_parser_33;
+        ++m_cursor;
+        { return scan(); }
+    }
 
 
         }
@@ -7780,9 +7646,9 @@ basic_json_parser_64:
         @brief parse floating point number
 
         This function (and its overloads) serves to select the most approprate
-        standard floating point number parsing function (i.e., `std::strtof`,
-        `std::strtod`, or `std::strtold`) based on the type supplied via the
-        first parameter. Set this to @a static_cast<number_float_t>(nullptr).
+        standard floating point number parsing function based on the type
+        supplied via the first parameter.  Set this to
+        @a static_cast<number_float_t*>(nullptr).
 
         @param[in] type  the @ref number_float_t in use
 
@@ -7801,45 +7667,135 @@ basic_json_parser_64:
             return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
         }
 
-        /// @copydoc str_to_float_t
-        double str_to_float_t(double*, char** endptr) const
+        /*!
+        @brief parse floating point number
+
+        This function (and its overloads) serves to select the most approprate
+        standard floating point number parsing function based on the type
+        supplied via the first parameter.  Set this to
+        @a static_cast<number_float_t*>(nullptr).
+
+        @param type  the @ref number_float_t in use
+
+        @param endptr  recieves a pointer to the first character after the number
+
+        @return the floating point number
+        */
+        double str_to_float_t(double* /* type */, char** endptr) const
         {
             return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
         }
 
-        /// @copydoc str_to_float_t
-        float str_to_float_t(float*, char** endptr) const
+        /*!
+        @brief parse floating point number
+
+        This function (and its overloads) serves to select the most approprate
+        standard floating point number parsing function based on the type
+        supplied via the first parameter.  Set this to
+        @a static_cast<number_float_t*>(nullptr).
+
+        @param type  the @ref number_float_t in use
+
+        @param endptr  recieves a pointer to the first character after the number
+
+        @return the floating point number
+        */
+        float str_to_float_t(float* /* type */, char** endptr) const
         {
             return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
         }
 
+        /*!
+        @brief static_cast between two types and indicate if it results in error
+
+        This function performs a static_cast between @a source and @a dest.  It 
+        then checks if a static_cast back to @a dest produces an error.
+
+        @param[in] source  the value to cast from 
+
+        @param[out] dest  the value to cast to
+
+        @return @a true if the cast was performed without error, @a false otherwise
+        */
+        template <typename T_A, typename T_B>
+        bool attempt_cast(T_A source, T_B & dest) const
+        {
+            dest = static_cast<T_B>(source);
+            return (source == static_cast<T_A>(dest));
+        }
+
         /*!
         @brief return number value for number tokens
 
-        This function translates the last token into a floating point number.
-        The pointer m_start points to the beginning of the parsed number. We
-        pass this pointer to std::strtod which sets endptr to the first
-        character past the converted number. If this pointer is not the same as
-        m_cursor, then either more or less characters have been used during the
-        comparison. This can happen for inputs like "01" which will be treated
-        like number 0 followed by number 1.
+        This function translates the last token into the most appropriate 
+        number type (either integer, unsigned integer or floating point), 
+        which is passed back to the caller via the result parameter. The pointer 
+        @a m_start points to the beginning of the parsed number. We first examine
+        the first character to determine the sign of the number and then pass
+        this pointer to either @a std::strtoull (if positive) or @a std::strtoll
+        (if negative), both of which set @a endptr to the first character past the 
+        converted number. If this pointer is not the same as @a m_cursor, then 
+        either more or less characters have been used during the comparison. 
+        
+        This can happen for inputs like "01" which will be treated like number 0 
+        followed by number 1.  This will also occur for valid floating point 
+        inputs like "12e3" will be incorrectly read as 12.  Numbers that are too
+        large or too small for a signed/unsigned long long will cause a range
+        error (@a errno set to ERANGE). The parsed number is cast to a @ref
+        number_integer_t/@ref number_unsigned_t using the helper function @ref attempt_cast,
+        which returns @a false if the cast could not be peformed without error.
 
-        @return the result of the number conversion or NAN if the conversion
-        read past the current token. The latter case needs to be treated by the
-        caller function.
+        In any of these cases (more/less characters read, range error or a cast
+        error) the pointer is passed to @a std:strtod, which also sets @a endptr to the
+        first character past the converted number. The resulting @ref number_float_t 
+        is then cast to a @ref number_integer_t/@ref number_unsigned_t using
+        @ref attempt_cast and if no error occurs is stored in that form, otherwise
+        it is stored as a @ref number_float_t.
+        
+        A final comparison is made of @a endptr and if still not the same as 
+        @ref m_cursor a bad input is assumed and @a result parameter is set to NAN.        
 
-        @throw std::range_error if passed value is out of range
+        @param[out] result  @ref basic_json object to receive the number, or NAN if the
+        conversion read past the current token. The latter case needs to be 
+        treated by the caller function.
         */
-        number_float_t get_number() const
+        void get_number(basic_json& result) const
         {
-            // conversion
             typename string_t::value_type* endptr;
             assert(m_start != nullptr);
-            number_float_t float_val = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
+            errno = 0;
+            
+            // Attempt to parse it as an integer - first checking for a negative number
+            if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
+            {
+                // Positive, parse with strtoull and attempt cast to number_unsigned_t
+                if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr, 10), result.m_value.number_unsigned))
+                    result.m_type = value_t::number_unsigned;
+                else result.m_type = value_t::number_float;  // Cast failed due to overflow - store as float
+            }
+            else
+            {
+                // Negative, parse with strtoll and attempt cast to number_integer_t
+                if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr, 10), result.m_value.number_unsigned))
+                    result.m_type = value_t::number_integer;
+                else result.m_type = value_t::number_float;  // Cast failed due to overflow - store as float
+            }
 
-            // return float_val if the whole number was translated and NAN
-            // otherwise
-            return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
+            // Check the end of the number was reached and no range error occurred
+            if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE) result.m_type = value_t::number_float;
+
+            if (result.m_type  == value_t::number_float)
+            {
+                // Either the number won't fit in an integer (range error from strtoull/strtoll or overflow on cast) or there was 
+                // something else after the number, which could be an exponent
+                
+                // Parse with strtod
+                result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
+
+                // Anything after the number is an error
+                if(reinterpret_cast<lexer_char_t*>(endptr) != m_cursor) 
+                    throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
+            }
         }
 
       private:
@@ -8069,32 +8025,8 @@ basic_json_parser_64:
 
                 case lexer::token_type::value_number:
                 {
-                    result.m_value = m_lexer.get_number();
-
-                    // NAN is returned if token could not be translated
-                    // completely
-                    if (std::isnan(result.m_value.number_float))
-                    {
-                        throw std::invalid_argument(std::string("parse error - ") +
-                                                    m_lexer.get_token() + " is not a number");
-                    }
-
+                    m_lexer.get_number(result);
                     get_token();
-
-                    // check if conversion loses precision (special case -0.0 always loses precision)
-                    const auto int_val = static_cast<number_integer_t>(result.m_value.number_float);
-                    if (result.m_value.number_float == static_cast<number_float_t>(int_val) and
-                            result.m_value.number_integer != json_value(-0.0f).number_integer)
-                    {
-                        // we would not lose precision -> return int
-                        result.m_type = value_t::number_integer;
-                        result.m_value = int_val;
-                    }
-                    else
-                    {
-                        // we would lose precision -> return float
-                        result.m_type = value_t::number_float;
-                    }
                     break;
                 }
 
@@ -8234,3 +8166,5 @@ inline nlohmann::json operator "" _json(const char* s, std::size_t)
 #endif
 
 #endif
+
+
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index ce2a18f6..d76f8ca2 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -124,6 +124,8 @@ default; will be used in @ref string_t)
 in @ref boolean_t)
 @tparam NumberIntegerType type for JSON integer numbers (@c `int64_t` by
 default; will be used in @ref number_integer_t)
+@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c `uint64_t` by
+default; will be used in @ref number_unsigned_t)
 @tparam NumberFloatType type for JSON floating-point numbers (@c `double` by
 default; will be used in @ref number_float_t)
 @tparam AllocatorType type of the allocator to use (@c `std::allocator` by
@@ -185,6 +187,7 @@ template <
     class StringType = std::string,
     class BooleanType = bool,
     class NumberIntegerType = int64_t,
+    class NumberUnsignedType = uint64_t,
     class NumberFloatType = double,
     template<typename U> class AllocatorType = std::allocator
     >
@@ -197,6 +200,7 @@ class basic_json
           StringType,
           BooleanType,
           NumberIntegerType,
+          NumberUnsignedType,
           NumberFloatType,
           AllocatorType>;
 
@@ -481,9 +485,10 @@ class basic_json
     > permitted.
 
     This description includes both integer and floating-point numbers. However,
-    C++ allows more precise storage if it is known whether the number is an
-    integer or a floating-point number. Therefore, two different types, @ref
-    number_integer_t and @ref number_float_t are used.
+    C++ allows more precise storage if it is known whether the number is a 
+    signed integer, an unsigned integer or a floating-point number. Therefore,
+    three different types, @ref number_integer_t,  @ref number_unsigned_t and 
+    @ref number_float_t are used.
 
     To store integer numbers in C++, a type is defined by the template
     parameter @a NumberIntegerType which chooses the type to use.
@@ -516,7 +521,7 @@ class basic_json
     that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
     that are out of range will yield over/underflow when used in a constructor.
     During deserialization, too large or small integer numbers will be
-    automatically be stored as @ref number_float_t.
+    automatically be stored as @ref number_unsigned_t or @ref number_float_t.
 
     [RFC 7159](http://rfc7159.net/rfc7159) further states:
     > Note that when such software is used, numbers that are integers and are
@@ -532,10 +537,84 @@ class basic_json
 
     @sa @ref number_float_t -- type for number values (floating-point)
 
+    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
+
     @since version 1.0.0
     */
     using number_integer_t = NumberIntegerType;
 
+    /*!
+    @brief a type for a number (unsigned)
+
+    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+    > The representation of numbers is similar to that used in most programming
+    > languages. A number is represented in base 10 using decimal digits. It
+    > contains an integer component that may be prefixed with an optional minus
+    > sign, which may be followed by a fraction part and/or an exponent part.
+    > Leading zeros are not allowed. (...) Numeric values that cannot be
+    > represented in the grammar below (such as Infinity and NaN) are not
+    > permitted.
+
+    This description includes both integer and floating-point numbers. However,
+    C++ allows more precise storage if it is known whether the number is a 
+    signed integer, an unsigned integer or a floating-point number. Therefore,
+    three different types, @ref number_integer_t,  @ref number_unsigned_t and 
+    @ref number_float_t are used.
+
+    To store unsigned integer numbers in C++, a type is defined by the template
+    parameter @a NumberUnsignedType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a NumberUnsignedType (`uint64_t`), the default
+    value for @a number_unsigned_t is:
+
+    @code {.cpp}
+    uint64_t
+    @endcode
+
+    #### Default behavior
+
+    - The restrictions about leading zeros is not enforced in C++. Instead,
+      leading zeros in integer literals lead to an interpretation as octal
+      number. Internally, the value will be stored as decimal number. For
+      instance, the C++ integer literal `010` will be serialized to `8`. During
+      deserialization, leading zeros yield an error.
+    - Not-a-number (NaN) values will be serialized to `null`.
+
+    #### Limits
+
+    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+    > An implementation may set limits on the range and precision of numbers.
+
+    When the default type is used, the maximal integer number that can be
+    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer number
+    that can be stored is `0`. Integer numbers
+    that are out of range will yield over/underflow when used in a constructor.
+    During deserialization, too large or small integer numbers will be
+    automatically be stored as @ref number_integer_t or @ref number_float_t.
+
+    [RFC 7159](http://rfc7159.net/rfc7159) further states:
+    > Note that when such software is used, numbers that are integers and are
+    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+    > that implementations will agree exactly on their numeric values.
+
+    As this range is a subrange (when considered in conjunction with the
+    number_integer_t type) of the exactly supported range [0, UINT64_MAX], this 
+    class's integer type is interoperable.
+
+    #### Storage
+
+    Integer number values are stored directly inside a @ref basic_json type.
+
+    @sa @ref number_float_t -- type for number values (floating-point)
+
+    @sa @ref number_integer_t -- type for number values (integer)
+
+    @since version 2.0.0
+    */
+    using number_unsigned_t = NumberUnsignedType;
+    
     /*!
     @brief a type for a number (floating-point)
 
@@ -549,9 +628,10 @@ class basic_json
     > permitted.
 
     This description includes both integer and floating-point numbers. However,
-    C++ allows more precise storage if it is known whether the number is an
-    integer or a floating-point number. Therefore, two different types, @ref
-    number_integer_t and @ref number_float_t are used.
+    C++ allows more precise storage if it is known whether the number is a 
+    signed integer, an unsigned integer or a floating-point number. Therefore,
+    three different types, @ref number_integer_t,  @ref number_unsigned_t and 
+    @ref number_float_t are used.
 
     To store floating-point numbers in C++, a type is defined by the template
     parameter @a NumberFloatType which chooses the type to use.
@@ -597,6 +677,8 @@ class basic_json
 
     @sa @ref number_integer_t -- type for number values (integer)
 
+    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
+
     @since version 1.0.0
     */
     using number_float_t = NumberFloatType;
@@ -626,6 +708,7 @@ class basic_json
         string,         ///< string value
         boolean,        ///< boolean value
         number_integer, ///< number value (integer)
+        number_unsigned,///< number value (unsigned integer)
         number_float,   ///< number value (floating-point)
         discarded       ///< discarded by the the parser callback function
     };
@@ -669,6 +752,8 @@ class basic_json
         boolean_t boolean;
         /// number (integer)
         number_integer_t number_integer;
+        /// number (unsigned integer)
+        number_unsigned_t number_unsigned;
         /// number (floating-point)
         number_float_t number_float;
 
@@ -678,6 +763,8 @@ class basic_json
         json_value(boolean_t v) noexcept : boolean(v) {}
         /// constructor for numbers (integer)
         json_value(number_integer_t v) noexcept : number_integer(v) {}
+        /// constructor for numbers (unsigned)
+        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
         /// constructor for numbers (floating-point)
         json_value(number_float_t v) noexcept : number_float(v) {}
         /// constructor for empty values of a given type
@@ -714,6 +801,12 @@ class basic_json
                     number_integer = number_integer_t(0);
                     break;
                 }
+                
+                case value_t::number_unsigned:
+                {
+                    number_unsigned = number_unsigned_t(0);
+                    break;
+                }
 
                 case value_t::number_float:
                 {
@@ -870,6 +963,8 @@ class basic_json
     (floating-point) value
     @sa @ref basic_json(const number_integer_t) -- create a number (integer)
     value
+    @sa @ref basic_json(const number_unsigned_t) -- create a number (unsigned)
+    value
 
     @since version 1.0.0
     */
@@ -1171,7 +1266,8 @@ class basic_json
              typename std::enable_if<
                  not (std::is_same<T, int>::value)
                  and std::is_same<T, number_integer_t>::value
-                 , int>::type = 0>
+                 , int>::type
+             = 0>
     basic_json(const number_integer_t val)
         : m_type(value_t::number_integer), m_value(val)
     {}
@@ -1234,13 +1330,74 @@ class basic_json
     template<typename CompatibleNumberIntegerType, typename
              std::enable_if<
                  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
-                 std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
+                 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and 
+                 std::numeric_limits<CompatibleNumberIntegerType>::is_signed, 
+                 CompatibleNumberIntegerType>::type
              = 0>
     basic_json(const CompatibleNumberIntegerType val) noexcept
         : m_type(value_t::number_integer),
           m_value(static_cast<number_integer_t>(val))
     {}
 
+    /*!
+    @brief create an unsigned integer number (explicit)
+
+    Create an unsigned integer number JSON value with a given content.
+
+    @tparam T  helper type to compare number_unsigned_t and unsigned int 
+    (not visible in) the interface.
+
+    @param[in] val  an integer to create a JSON number from
+
+    @complexity Constant.
+
+    @sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number
+    value (unsigned integer) from a compatible number type
+
+    @since version 2.0.0
+    */
+    template<typename T,
+             typename std::enable_if<
+                 not (std::is_same<T, int>::value)
+                 and std::is_same<T, number_unsigned_t>::value
+                 , int>::type
+             = 0>
+    basic_json(const number_unsigned_t val)
+        : m_type(value_t::number_unsigned), m_value(val)
+    {}
+    
+    /*!
+    @brief create an unsigned number (implicit)
+
+    Create an unsigned number JSON value with a given content. This constructor
+    allows any type that can be used to construct values of type @ref
+    number_unsigned_t. Examples may include the types `unsigned int`, `uint32_t`,
+    or `unsigned short`.
+
+    @tparam CompatibleNumberUnsignedType an integer type which is compatible to
+    @ref number_unsigned_t.
+
+    @param[in] val  an unsigned integer to create a JSON number from
+
+    @complexity Constant.
+
+    @sa @ref basic_json(const number_unsigned_t) -- create a number value
+    (unsigned)
+
+    @since version 2.0.0
+    */
+    template<typename CompatibleNumberUnsignedType, typename
+             std::enable_if<
+                 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
+                 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and 
+                 !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, 
+                 CompatibleNumberUnsignedType>::type
+             = 0>
+    basic_json(const CompatibleNumberUnsignedType val) noexcept
+        : m_type(value_t::number_unsigned),
+          m_value(static_cast<number_unsigned_t>(val))
+    {}
+
     /*!
     @brief create a floating-point number (explicit)
 
@@ -1600,6 +1757,7 @@ class basic_json
             case value_t::boolean:
             case value_t::number_float:
             case value_t::number_integer:
+            case value_t::number_unsigned:
             case value_t::string:
             {
                 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
@@ -1623,6 +1781,13 @@ class basic_json
                 m_value.number_integer = first.m_object->m_value.number_integer;
                 break;
             }
+            
+            case value_t::number_unsigned:
+            {
+                assert(first.m_object != nullptr);
+                m_value.number_unsigned = first.m_object->m_value.number_unsigned;
+                break;
+            }
 
             case value_t::number_float:
             {
@@ -1726,6 +1891,12 @@ class basic_json
                 m_value = other.m_value.number_integer;
                 break;
             }
+            
+            case value_t::number_unsigned:
+            {
+                m_value = other.m_value.number_unsigned;
+                break;
+            }
 
             case value_t::number_float:
             {
@@ -2004,15 +2175,17 @@ class basic_json
     This function returns true iff the JSON value is a number. This includes
     both integer and floating-point values.
 
-    @return `true` if type is number (regardless whether integer or
-    floating-type), `false` otherwise.
+    @return `true` if type is number (regardless whether integer, unsigned
+    integer or floating-type), `false` otherwise.
 
     @complexity Constant.
 
     @liveexample{The following code exemplifies @ref is_number for all JSON
     types.,is_number}
 
-    @sa @ref is_number_integer() -- check if value is an integer number
+    @sa @ref is_number_integer() -- check if value is an integer or unsigned 
+    integer number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer number
     @sa @ref is_number_float() -- check if value is a floating-point number
 
     @since version 1.0.0
@@ -2025,10 +2198,11 @@ class basic_json
     /*!
     @brief return whether value is an integer number
 
-    This function returns true iff the JSON value is an integer number. This
-    excludes floating-point values.
+    This function returns true iff the JSON value is an integer or unsigned 
+    integer number. This excludes floating-point values.
 
-    @return `true` if type is an integer number, `false` otherwise.
+    @return `true` if type is an integer or unsigned integer number, `false` 
+    otherwise.
 
     @complexity Constant.
 
@@ -2036,20 +2210,43 @@ class basic_json
     JSON types.,is_number_integer}
 
     @sa @ref is_number() -- check if value is a number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer number
     @sa @ref is_number_float() -- check if value is a floating-point number
 
     @since version 1.0.0
     */
     bool is_number_integer() const noexcept
     {
-        return m_type == value_t::number_integer;
+        return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
+    }
+    
+    /*!
+    @brief return whether value is an unsigned integer number
+
+    This function returns true iff the JSON value is an unsigned integer number. 
+    This excludes floating-point and (signed) integer values.
+
+    @return `true` if type is an unsigned integer number, `false` otherwise.
+
+    @complexity Constant.
+
+    @sa @ref is_number() -- check if value is a number
+    @sa @ref is_number_integer() -- check if value is an integer or unsigned 
+    integer number
+    @sa @ref is_number_float() -- check if value is a floating-point number
+
+    @since version 2.0.0
+    */
+    bool is_number_unsigned() const noexcept
+    {
+        return m_type == value_t::number_unsigned;
     }
 
     /*!
     @brief return whether value is a floating-point number
 
     This function returns true iff the JSON value is a floating-point number.
-    This excludes integer values.
+    This excludes integer and unsigned integer values.
 
     @return `true` if type is a floating-point number, `false` otherwise.
 
@@ -2060,6 +2257,7 @@ class basic_json
 
     @sa @ref is_number() -- check if value is number
     @sa @ref is_number_integer() -- check if value is an integer number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer number
 
     @since version 1.0.0
     */
@@ -2327,6 +2525,11 @@ class basic_json
             {
                 return static_cast<T>(m_value.number_integer);
             }
+            
+            case value_t::number_unsigned:
+            {
+                return static_cast<T>(m_value.number_unsigned);
+            }
 
             case value_t::number_float:
             {
@@ -2412,7 +2615,19 @@ class basic_json
     {
         return is_number_integer() ? &m_value.number_integer : nullptr;
     }
+    
+    /// get a pointer to the value (unsigned number)
+    number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
 
+    /// get a pointer to the value (unsigned number)
+    const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
+    
     /// get a pointer to the value (floating-point number)
     number_float_t* get_impl_ptr(number_float_t*) noexcept
     {
@@ -2510,8 +2725,8 @@ class basic_json
     @warning The pointer becomes invalid if the underlying JSON object changes.
 
     @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.
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 
+    @ref number_unsigned_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
@@ -2561,8 +2776,8 @@ class basic_json
     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.
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 
+    @ref number_unsigned_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
@@ -2680,14 +2895,14 @@ class basic_json
 
     @since version 1.0.0
     */
-    template < typename ValueType, typename
-               std::enable_if <
-                   not std::is_pointer<ValueType>::value
-                   and not std::is_same<ValueType, typename string_t::value_type>::value
+    template<typename ValueType, typename
+             std::enable_if<
+                 not std::is_pointer<ValueType>::value
+                 and not std::is_same<ValueType, typename string_t::value_type>::value
 #ifndef _MSC_VER  // Fix for issue #167 operator<< abiguity under VS2015
-                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
+                 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
 #endif
-                   , int >::type = 0 >
+                 , int>::type = 0>
     operator ValueType() const
     {
         // delegate the call to get<>() const
@@ -3441,6 +3656,7 @@ class basic_json
             case value_t::boolean:
             case value_t::number_float:
             case value_t::number_integer:
+            case value_t::number_unsigned:
             case value_t::string:
             {
                 if (not pos.m_it.primitive_iterator.is_begin())
@@ -3546,6 +3762,7 @@ class basic_json
             case value_t::boolean:
             case value_t::number_float:
             case value_t::number_integer:
+            case value_t::number_unsigned:
             case value_t::string:
             {
                 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
@@ -4235,6 +4452,12 @@ class basic_json
                 break;
             }
 
+            case value_t::number_unsigned:
+            {
+                m_value.number_unsigned = 0;
+                break;
+            }
+
             case value_t::number_float:
             {
                 m_value.number_float = 0.0;
@@ -4773,14 +4996,15 @@ class basic_json
     */
     friend bool operator<(const value_t lhs, const value_t rhs)
     {
-        static constexpr std::array<uint8_t, 7> order = {{
+        static constexpr std::array<uint8_t, 8> order = {{
                 0, // null
                 3, // object
                 4, // array
                 5, // string
                 1, // boolean
                 2, // integer
-                2  // float
+                2, // unsigned
+                2, // float
             }
         };
 
@@ -4856,6 +5080,10 @@ class basic_json
                 {
                     return lhs.m_value.number_integer == rhs.m_value.number_integer;
                 }
+                case value_t::number_unsigned:
+                {
+                    return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
+                }
                 case value_t::number_float:
                 {
                     return lhs.m_value.number_float == rhs.m_value.number_float;
@@ -4874,6 +5102,23 @@ class basic_json
         {
             return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
         }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
+        {
+            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
+        }
+        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+        }
+
         return false;
     }
 
@@ -5025,6 +5270,10 @@ class basic_json
                 {
                     return lhs.m_value.number_integer < rhs.m_value.number_integer;
                 }
+                case value_t::number_unsigned:
+                {
+                    return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
+                }
                 case value_t::number_float:
                 {
                     return lhs.m_value.number_float < rhs.m_value.number_float;
@@ -5037,13 +5286,27 @@ class basic_json
         }
         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
         {
-            return static_cast<number_float_t>(lhs.m_value.number_integer) <
-                   rhs.m_value.number_float;
+            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
         }
         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
         {
-            return lhs.m_value.number_float <
-                   static_cast<number_float_t>(rhs.m_value.number_integer);
+            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
+        {
+            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
         }
 
         // We only reach this line if we cannot compare values. In that case,
@@ -5608,6 +5871,12 @@ class basic_json
                 return;
             }
 
+            case value_t::number_unsigned:
+            {
+                o << m_value.number_unsigned;
+                return;
+            }
+
             case value_t::number_float:
             {
                 // If the number is an integer then output as a fixed with with
@@ -7059,9 +7328,9 @@ class basic_json
         @brief parse floating point number
 
         This function (and its overloads) serves to select the most approprate
-        standard floating point number parsing function (i.e., `std::strtof`,
-        `std::strtod`, or `std::strtold`) based on the type supplied via the
-        first parameter. Set this to @a static_cast<number_float_t>(nullptr).
+        standard floating point number parsing function based on the type
+        supplied via the first parameter.  Set this to
+        @a static_cast<number_float_t*>(nullptr).
 
         @param[in] type  the @ref number_float_t in use
 
@@ -7080,45 +7349,135 @@ class basic_json
             return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
         }
 
-        /// @copydoc str_to_float_t
-        double str_to_float_t(double*, char** endptr) const
+        /*!
+        @brief parse floating point number
+
+        This function (and its overloads) serves to select the most approprate
+        standard floating point number parsing function based on the type
+        supplied via the first parameter.  Set this to
+        @a static_cast<number_float_t*>(nullptr).
+
+        @param type  the @ref number_float_t in use
+
+        @param endptr  recieves a pointer to the first character after the number
+
+        @return the floating point number
+        */
+        double str_to_float_t(double* /* type */, char** endptr) const
         {
             return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
         }
 
-        /// @copydoc str_to_float_t
-        float str_to_float_t(float*, char** endptr) const
+        /*!
+        @brief parse floating point number
+
+        This function (and its overloads) serves to select the most approprate
+        standard floating point number parsing function based on the type
+        supplied via the first parameter.  Set this to
+        @a static_cast<number_float_t*>(nullptr).
+
+        @param type  the @ref number_float_t in use
+
+        @param endptr  recieves a pointer to the first character after the number
+
+        @return the floating point number
+        */
+        float str_to_float_t(float* /* type */, char** endptr) const
         {
             return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
         }
 
+        /*!
+        @brief static_cast between two types and indicate if it results in error
+
+        This function performs a static_cast between @a source and @a dest.  It 
+        then checks if a static_cast back to @a dest produces an error.
+
+        @param[in] source  the value to cast from 
+
+        @param[out] dest  the value to cast to
+
+        @return @a true if the cast was performed without error, @a false otherwise
+        */
+        template <typename T_A, typename T_B>
+        bool attempt_cast(T_A source, T_B & dest) const
+        {
+            dest = static_cast<T_B>(source);
+            return (source == static_cast<T_A>(dest));
+        }
+
         /*!
         @brief return number value for number tokens
 
-        This function translates the last token into a floating point number.
-        The pointer m_start points to the beginning of the parsed number. We
-        pass this pointer to std::strtod which sets endptr to the first
-        character past the converted number. If this pointer is not the same as
-        m_cursor, then either more or less characters have been used during the
-        comparison. This can happen for inputs like "01" which will be treated
-        like number 0 followed by number 1.
+        This function translates the last token into the most appropriate 
+        number type (either integer, unsigned integer or floating point), 
+        which is passed back to the caller via the result parameter. The pointer 
+        @a m_start points to the beginning of the parsed number. We first examine
+        the first character to determine the sign of the number and then pass
+        this pointer to either @a std::strtoull (if positive) or @a std::strtoll
+        (if negative), both of which set @a endptr to the first character past the 
+        converted number. If this pointer is not the same as @a m_cursor, then 
+        either more or less characters have been used during the comparison. 
+        
+        This can happen for inputs like "01" which will be treated like number 0 
+        followed by number 1.  This will also occur for valid floating point 
+        inputs like "12e3" will be incorrectly read as 12.  Numbers that are too
+        large or too small for a signed/unsigned long long will cause a range
+        error (@a errno set to ERANGE). The parsed number is cast to a @ref
+        number_integer_t/@ref number_unsigned_t using the helper function @ref attempt_cast,
+        which returns @a false if the cast could not be peformed without error.
 
-        @return the result of the number conversion or NAN if the conversion
-        read past the current token. The latter case needs to be treated by the
-        caller function.
+        In any of these cases (more/less characters read, range error or a cast
+        error) the pointer is passed to @a std:strtod, which also sets @a endptr to the
+        first character past the converted number. The resulting @ref number_float_t 
+        is then cast to a @ref number_integer_t/@ref number_unsigned_t using
+        @ref attempt_cast and if no error occurs is stored in that form, otherwise
+        it is stored as a @ref number_float_t.
+        
+        A final comparison is made of @a endptr and if still not the same as 
+        @ref m_cursor a bad input is assumed and @a result parameter is set to NAN.        
 
-        @throw std::range_error if passed value is out of range
+        @param[out] result  @ref basic_json object to receive the number, or NAN if the
+        conversion read past the current token. The latter case needs to be 
+        treated by the caller function.
         */
-        number_float_t get_number() const
+        void get_number(basic_json& result) const
         {
-            // conversion
             typename string_t::value_type* endptr;
             assert(m_start != nullptr);
-            number_float_t float_val = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
+            errno = 0;
+            
+            // Attempt to parse it as an integer - first checking for a negative number
+            if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
+            {
+                // Positive, parse with strtoull and attempt cast to number_unsigned_t
+                if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr, 10), result.m_value.number_unsigned))
+                    result.m_type = value_t::number_unsigned;
+                else result.m_type = value_t::number_float;  // Cast failed due to overflow - store as float
+            }
+            else
+            {
+                // Negative, parse with strtoll and attempt cast to number_integer_t
+                if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr, 10), result.m_value.number_unsigned))
+                    result.m_type = value_t::number_integer;
+                else result.m_type = value_t::number_float;  // Cast failed due to overflow - store as float
+            }
 
-            // return float_val if the whole number was translated and NAN
-            // otherwise
-            return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
+            // Check the end of the number was reached and no range error occurred
+            if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE) result.m_type = value_t::number_float;
+
+            if (result.m_type  == value_t::number_float)
+            {
+                // Either the number won't fit in an integer (range error from strtoull/strtoll or overflow on cast) or there was 
+                // something else after the number, which could be an exponent
+                
+                // Parse with strtod
+                result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
+
+                // Anything after the number is an error
+                if(reinterpret_cast<lexer_char_t*>(endptr) != m_cursor) 
+                    throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
+            }
         }
 
       private:
@@ -7348,32 +7707,8 @@ class basic_json
 
                 case lexer::token_type::value_number:
                 {
-                    result.m_value = m_lexer.get_number();
-
-                    // NAN is returned if token could not be translated
-                    // completely
-                    if (std::isnan(result.m_value.number_float))
-                    {
-                        throw std::invalid_argument(std::string("parse error - ") +
-                                                    m_lexer.get_token() + " is not a number");
-                    }
-
+                    m_lexer.get_number(result);
                     get_token();
-
-                    // check if conversion loses precision (special case -0.0 always loses precision)
-                    const auto int_val = static_cast<number_integer_t>(result.m_value.number_float);
-                    if (result.m_value.number_float == static_cast<number_float_t>(int_val) and
-                            result.m_value.number_integer != json_value(-0.0f).number_integer)
-                    {
-                        // we would not lose precision -> return int
-                        result.m_type = value_t::number_integer;
-                        result.m_value = int_val;
-                    }
-                    else
-                    {
-                        // we would lose precision -> return float
-                        result.m_type = value_t::number_float;
-                    }
                     break;
                 }
 
@@ -7513,3 +7848,5 @@ inline nlohmann::json operator "" _json(const char* s, std::size_t)
 #endif
 
 #endif
+
+
diff --git a/test/unit.cpp b/test/unit.cpp
index 46d52ad5..519f760b 100644
--- a/test/unit.cpp
+++ b/test/unit.cpp
@@ -83,6 +83,13 @@ TEST_CASE("constructors")
             CHECK(j.type() == t);
         }
 
+        SECTION("number_unsigned")
+        {
+            auto t = json::value_t::number_unsigned;
+            json j(t);
+            CHECK(j.type() == t);
+        }
+
         SECTION("number_float")
         {
             auto t = json::value_t::number_float;
@@ -120,7 +127,7 @@ TEST_CASE("constructors")
 
         SECTION("filled object")
         {
-            json::object_t o {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}};
+            json::object_t o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
             json j(o);
             CHECK(j.type() == json::value_t::object);
         }
@@ -129,12 +136,12 @@ TEST_CASE("constructors")
     SECTION("create an object (implicit)")
     {
         // reference object
-        json::object_t o_reference {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}};
+        json::object_t o_reference {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
         json j_reference(o_reference);
 
         SECTION("std::map<json::string_t, json>")
         {
-            std::map<json::string_t, json> o {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}};
+            std::map<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
             json j(o);
             CHECK(j.type() == json::value_t::object);
             CHECK(j == j_reference);
@@ -142,7 +149,7 @@ TEST_CASE("constructors")
 
         SECTION("std::map<const char*, json>")
         {
-            std::map<const char*, json> o {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}};
+            std::map<const char*, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
             json j(o);
             CHECK(j.type() == json::value_t::object);
             CHECK(j == j_reference);
@@ -150,7 +157,7 @@ TEST_CASE("constructors")
 
         SECTION("std::multimap<json::string_t, json>")
         {
-            std::multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}};
+            std::multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
             json j(o);
             CHECK(j.type() == json::value_t::object);
             CHECK(j == j_reference);
@@ -158,7 +165,7 @@ TEST_CASE("constructors")
 
         SECTION("std::unordered_map<json::string_t, json>")
         {
-            std::unordered_map<json::string_t, json> o {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}};
+            std::unordered_map<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
             json j(o);
             CHECK(j.type() == json::value_t::object);
             CHECK(j == j_reference);
@@ -166,7 +173,7 @@ TEST_CASE("constructors")
 
         SECTION("std::unordered_multimap<json::string_t, json>")
         {
-            std::unordered_multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}};
+            std::unordered_multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
             json j(o);
             CHECK(j.type() == json::value_t::object);
             CHECK(j == j_reference);
@@ -174,7 +181,7 @@ TEST_CASE("constructors")
 
         SECTION("associative container literal")
         {
-            json j({{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}});
+            json j({{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}});
             CHECK(j.type() == json::value_t::object);
             CHECK(j == j_reference);
         }
@@ -191,7 +198,7 @@ TEST_CASE("constructors")
 
         SECTION("filled array")
         {
-            json::array_t a {json(1), json(2.2), json(false), json("string"), json()};
+            json::array_t a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
             json j(a);
             CHECK(j.type() == json::value_t::array);
         }
@@ -200,12 +207,12 @@ TEST_CASE("constructors")
     SECTION("create an array (implicit)")
     {
         // reference array
-        json::array_t a_reference {json(1), json(2.2), json(false), json("string"), json()};
+        json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
         json j_reference(a_reference);
 
         SECTION("std::list<json>")
         {
-            std::list<json> a {json(1), json(2.2), json(false), json("string"), json()};
+            std::list<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
             json j(a);
             CHECK(j.type() == json::value_t::array);
             CHECK(j == j_reference);
@@ -213,7 +220,7 @@ TEST_CASE("constructors")
 
         SECTION("std::forward_list<json>")
         {
-            std::forward_list<json> a {json(1), json(2.2), json(false), json("string"), json()};
+            std::forward_list<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
             json j(a);
             CHECK(j.type() == json::value_t::array);
             CHECK(j == j_reference);
@@ -221,7 +228,7 @@ TEST_CASE("constructors")
 
         SECTION("std::array<json, 5>")
         {
-            std::array<json, 5> a {{json(1), json(2.2), json(false), json("string"), json()}};
+            std::array<json, 6> a {{json(1), json(1u), json(2.2), json(false), json("string"), json()}};
             json j(a);
             CHECK(j.type() == json::value_t::array);
             CHECK(j == j_reference);
@@ -229,7 +236,7 @@ TEST_CASE("constructors")
 
         SECTION("std::vector<json>")
         {
-            std::vector<json> a {json(1), json(2.2), json(false), json("string"), json()};
+            std::vector<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
             json j(a);
             CHECK(j.type() == json::value_t::array);
             CHECK(j == j_reference);
@@ -237,7 +244,7 @@ TEST_CASE("constructors")
 
         SECTION("std::deque<json>")
         {
-            std::deque<json> a {json(1), json(2.2), json(false), json("string"), json()};
+            std::deque<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
             json j(a);
             CHECK(j.type() == json::value_t::array);
             CHECK(j == j_reference);
@@ -245,7 +252,7 @@ TEST_CASE("constructors")
 
         SECTION("std::set<json>")
         {
-            std::set<json> a {json(1), json(2.2), json(false), json("string"), json()};
+            std::set<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
             json j(a);
             CHECK(j.type() == json::value_t::array);
             // we cannot really check for equality here
@@ -253,7 +260,7 @@ TEST_CASE("constructors")
 
         SECTION("std::unordered_set<json>")
         {
-            std::unordered_set<json> a {json(1), json(2.2), json(false), json("string"), json()};
+            std::unordered_set<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
             json j(a);
             CHECK(j.type() == json::value_t::array);
             // we cannot really check for equality here
@@ -261,7 +268,7 @@ TEST_CASE("constructors")
 
         SECTION("sequence container literal")
         {
-            json j({json(1), json(2.2), json(false), json("string"), json()});
+            json j({json(1), json(1u), json(2.2), json(false), json("string"), json()});
             CHECK(j.type() == json::value_t::array);
             CHECK(j == j_reference);
         }
@@ -363,9 +370,11 @@ TEST_CASE("constructors")
 
     SECTION("create an integer number (implicit)")
     {
-        // reference object
+        // reference objects
         json::number_integer_t n_reference = 42;
         json j_reference(n_reference);
+        json::number_unsigned_t n_unsigned_reference = 42;
+        json j_unsigned_reference(n_unsigned_reference);
 
         SECTION("short")
         {
@@ -379,8 +388,8 @@ TEST_CASE("constructors")
         {
             unsigned short n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("int")
@@ -395,8 +404,8 @@ TEST_CASE("constructors")
         {
             unsigned int n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("long")
@@ -409,10 +418,10 @@ TEST_CASE("constructors")
 
         SECTION("unsigned long")
         {
-            short n = 42;
+            unsigned long n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("long long")
@@ -427,8 +436,8 @@ TEST_CASE("constructors")
         {
             unsigned long long n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("int8_t")
@@ -531,96 +540,96 @@ TEST_CASE("constructors")
         {
             uint8_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint16_t")
         {
             uint16_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint32_t")
         {
             uint32_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint64_t")
         {
             uint64_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint_fast8_t")
         {
             uint_fast8_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint_fast16_t")
         {
             uint_fast16_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint_fast32_t")
         {
             uint_fast32_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint_fast64_t")
         {
             uint_fast64_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint_least8_t")
         {
             uint_least8_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint_least16_t")
         {
             uint_least16_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint_least32_t")
         {
             uint_least32_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("uint_least64_t")
         {
             uint_least64_t n = 42;
             json j(n);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("integer literal without suffix")
@@ -633,8 +642,8 @@ TEST_CASE("constructors")
         SECTION("integer literal with u suffix")
         {
             json j(42u);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("integer literal with l suffix")
@@ -647,8 +656,8 @@ TEST_CASE("constructors")
         SECTION("integer literal with ul suffix")
         {
             json j(42ul);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
 
         SECTION("integer literal with ll suffix")
@@ -661,8 +670,8 @@ TEST_CASE("constructors")
         SECTION("integer literal with ull suffix")
         {
             json j(42ull);
-            CHECK(j.type() == json::value_t::number_integer);
-            CHECK(j == j_reference);
+            CHECK(j.type() == json::value_t::number_unsigned);
+            CHECK(j == j_unsigned_reference);
         }
     }
 
@@ -835,6 +844,22 @@ TEST_CASE("constructors")
                 }
             }
 
+            SECTION("number (unsigned)")
+            {
+                SECTION("explicit")
+                {
+                    std::initializer_list<json> l = {json(1u)};
+                    json j(l);
+                    CHECK(j.type() == json::value_t::array);
+                }
+
+                SECTION("implicit")
+                {
+                    json j {1u};
+                    CHECK(j.type() == json::value_t::array);
+                }
+            }
+
             SECTION("number (floating-point)")
             {
                 SECTION("explicit")
@@ -856,14 +881,14 @@ TEST_CASE("constructors")
         {
             SECTION("explicit")
             {
-                std::initializer_list<json> l = {1, 42.23, true, nullptr, json::object_t(), json::array_t()};
+                std::initializer_list<json> l = {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()};
                 json j(l);
                 CHECK(j.type() == json::value_t::array);
             }
 
             SECTION("implicit")
             {
-                json j {1, 42.23, true, nullptr, json::object_t(), json::array_t()};
+                json j {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()};
                 CHECK(j.type() == json::value_t::array);
             }
         }
@@ -872,13 +897,13 @@ TEST_CASE("constructors")
         {
             SECTION("object")
             {
-                json j { {"one", 1}, {"two", 2.2}, {"three", false} };
+                json j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} };
                 CHECK(j.type() == json::value_t::object);
             }
 
             SECTION("array")
             {
-                json j { {"one", 1}, {"two", 2.2}, {"three", false}, 13 };
+                json j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} , 13 };
                 CHECK(j.type() == json::value_t::array);
             }
         }
@@ -893,14 +918,14 @@ TEST_CASE("constructors")
 
             SECTION("object")
             {
-                json j = json::object({ {"one", 1}, {"two", 2.2}, {"three", false} });
+                json j = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
                 CHECK(j.type() == json::value_t::object);
             }
 
             SECTION("object with error")
             {
-                CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 2.2}, {"three", false}, 13 }), std::logic_error);
-                CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 2.2}, {"three", false}, 13 }),
+                CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), std::logic_error);
+                CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
                 "cannot create object from initializer list");
             }
 
@@ -912,7 +937,7 @@ TEST_CASE("constructors")
 
             SECTION("array")
             {
-                json j = json::array({ {"one", 1}, {"two", 2.2}, {"three", false} });
+                json j = json::array({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
                 CHECK(j.type() == json::value_t::array);
             }
         }
@@ -920,7 +945,7 @@ TEST_CASE("constructors")
 
     SECTION("create an array of n copies of a given value")
     {
-        json v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2}}};
+        json v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
         json arr(3, v);
         CHECK(arr.size() == 3);
         for (auto& x : arr)
@@ -936,12 +961,12 @@ TEST_CASE("constructors")
             SECTION("json(begin(), end())")
             {
                 {
-                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                     json j_new(jobject.begin(), jobject.end());
                     CHECK(j_new == jobject);
                 }
                 {
-                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                     json j_new(jobject.cbegin(), jobject.cend());
                     CHECK(j_new == jobject);
                 }
@@ -950,12 +975,12 @@ TEST_CASE("constructors")
             SECTION("json(begin(), begin())")
             {
                 {
-                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                     json j_new(jobject.begin(), jobject.begin());
                     CHECK(j_new == json::object());
                 }
                 {
-                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                     json j_new(jobject.cbegin(), jobject.cbegin());
                     CHECK(j_new == json::object());
                 }
@@ -963,24 +988,24 @@ TEST_CASE("constructors")
 
             SECTION("construct from subrange")
             {
-                json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
+                json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
                 json j_new(jobject.find("b"), jobject.find("e"));
-                CHECK(j_new == json({{"b", 1}, {"c", 17}, {"d", false}}));
+                CHECK(j_new == json({{"b", 1}, {"c", 17u}, {"d", false}}));
             }
 
             SECTION("incompatible iterators")
             {
                 {
-                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
-                    json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
+                    json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                     CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), std::domain_error);
                     CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), std::domain_error);
                     CHECK_THROWS_WITH(json(jobject.begin(), jobject2.end()), "iterators are not compatible");
                     CHECK_THROWS_WITH(json(jobject2.begin(), jobject.end()), "iterators are not compatible");
                 }
                 {
-                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
-                    json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                    json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
+                    json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                     CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), std::domain_error);
                     CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), std::domain_error);
                     CHECK_THROWS_WITH(json(jobject.cbegin(), jobject2.cend()), "iterators are not compatible");
@@ -1114,6 +1139,20 @@ TEST_CASE("constructors")
                     }
                 }
 
+                SECTION("number (unsigned)")
+                {
+                    {
+                        json j = 17u;
+                        json j_new(j.begin(), j.end());
+                        CHECK(j == j_new);
+                    }
+                    {
+                        json j = 17u;
+                        json j_new(j.cbegin(), j.cend());
+                        CHECK(j == j_new);
+                    }
+                }
+
                 SECTION("number (floating point)")
                 {
                     {
@@ -1185,6 +1224,24 @@ TEST_CASE("constructors")
                     }
                 }
 
+                SECTION("number (integer)")
+                {
+                    {
+                        json j = 17u;
+                        CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range);
+                        CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range);
+                        CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range");
+                        CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range");
+                    }
+                    {
+                        json j = 17u;
+                        CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range);
+                        CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range);
+                        CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range");
+                        CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range");
+                    }
+                }
+
                 SECTION("number (floating point)")
                 {
                     {
@@ -1253,6 +1310,13 @@ TEST_CASE("other constructors and destructor")
             CHECK(j == k);
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j(42u);
+            json k(j);
+            CHECK(j == k);
+        }
+
         SECTION("number (floating-point)")
         {
             json j(42.23);
@@ -1263,7 +1327,7 @@ TEST_CASE("other constructors and destructor")
 
     SECTION("move constructor")
     {
-        json j {{"foo", "bar"}, {"baz", {1, 2, 3, 4}}, {"a", 42.23}, {"b", nullptr}};
+        json j {{"foo", "bar"}, {"baz", {1, 2, 3, 4}}, {"a", 42u}, {"b", 42.23}, {"c", nullptr}};
         CHECK(j.type() == json::value_t::object);
         json k(std::move(j));
         CHECK(k.type() == json::value_t::object);
@@ -1320,6 +1384,14 @@ TEST_CASE("other constructors and destructor")
             CHECK(j == k);
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j(42u);
+            json k;
+            k = j;
+            CHECK(j == k);
+        }
+
         SECTION("number (floating-point)")
         {
             json j(42.23);
@@ -1339,7 +1411,7 @@ TEST_CASE("other constructors and destructor")
 
         SECTION("array")
         {
-            auto j = new json {"foo", 1, false, 23.42};
+            auto j = new json {"foo", 1, 1u, false, 23.42};
             delete j;
         }
 
@@ -1362,6 +1434,7 @@ TEST_CASE("object inspection")
             CHECK(not j.is_boolean());
             CHECK(not j.is_number());
             CHECK(not j.is_number_integer());
+            CHECK(not j.is_number_unsigned());
             CHECK(not j.is_number_float());
             CHECK(j.is_object());
             CHECK(not j.is_array());
@@ -1373,11 +1446,12 @@ TEST_CASE("object inspection")
 
         SECTION("array")
         {
-            json j {"foo", 1, 42.23, false};
+            json j {"foo", 1, 1u, 42.23, false};
             CHECK(not j.is_null());
             CHECK(not j.is_boolean());
             CHECK(not j.is_number());
             CHECK(not j.is_number_integer());
+            CHECK(not j.is_number_unsigned());
             CHECK(not j.is_number_float());
             CHECK(not j.is_object());
             CHECK(j.is_array());
@@ -1394,6 +1468,7 @@ TEST_CASE("object inspection")
             CHECK(not j.is_boolean());
             CHECK(not j.is_number());
             CHECK(not j.is_number_integer());
+            CHECK(not j.is_number_unsigned());
             CHECK(not j.is_number_float());
             CHECK(not j.is_object());
             CHECK(not j.is_array());
@@ -1410,6 +1485,7 @@ TEST_CASE("object inspection")
             CHECK(j.is_boolean());
             CHECK(not j.is_number());
             CHECK(not j.is_number_integer());
+            CHECK(not j.is_number_unsigned());
             CHECK(not j.is_number_float());
             CHECK(not j.is_object());
             CHECK(not j.is_array());
@@ -1426,6 +1502,7 @@ TEST_CASE("object inspection")
             CHECK(not j.is_boolean());
             CHECK(not j.is_number());
             CHECK(not j.is_number_integer());
+            CHECK(not j.is_number_unsigned());
             CHECK(not j.is_number_float());
             CHECK(not j.is_object());
             CHECK(not j.is_array());
@@ -1442,6 +1519,24 @@ TEST_CASE("object inspection")
             CHECK(not j.is_boolean());
             CHECK(j.is_number());
             CHECK(j.is_number_integer());
+            CHECK(not j.is_number_unsigned());
+            CHECK(not j.is_number_float());
+            CHECK(not j.is_object());
+            CHECK(not j.is_array());
+            CHECK(not j.is_string());
+            CHECK(not j.is_discarded());
+            CHECK(j.is_primitive());
+            CHECK(not j.is_structured());
+        }
+
+        SECTION("number (unsigned)")
+        {
+            json j(42u);
+            CHECK(not j.is_null());
+            CHECK(not j.is_boolean());
+            CHECK(j.is_number());
+            CHECK(j.is_number_integer());
+            CHECK(j.is_number_unsigned());
             CHECK(not j.is_number_float());
             CHECK(not j.is_object());
             CHECK(not j.is_array());
@@ -1458,6 +1553,7 @@ TEST_CASE("object inspection")
             CHECK(not j.is_boolean());
             CHECK(j.is_number());
             CHECK(not j.is_number_integer());
+            CHECK(not j.is_number_unsigned());
             CHECK(j.is_number_float());
             CHECK(not j.is_object());
             CHECK(not j.is_array());
@@ -1474,6 +1570,7 @@ TEST_CASE("object inspection")
             CHECK(not j.is_boolean());
             CHECK(not j.is_number());
             CHECK(not j.is_number_integer());
+            CHECK(not j.is_number_unsigned());
             CHECK(not j.is_number_float());
             CHECK(not j.is_object());
             CHECK(not j.is_array());
@@ -1572,6 +1669,12 @@ TEST_CASE("object inspection")
             CHECK(j.type() == json::value_t::number_integer);
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j = 23u;
+            CHECK(j.type() == json::value_t::number_unsigned);
+        }
+
         SECTION("number (floating-point)")
         {
             json j = 42.23;
@@ -1623,6 +1726,13 @@ TEST_CASE("object inspection")
             CHECK(t == j.type());
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j = 23u;
+            json::value_t t = j;
+            CHECK(t == j.type());
+        }
+
         SECTION("number (floating-point)")
         {
             json j = 42.23;
@@ -1677,6 +1787,7 @@ TEST_CASE("value conversion")
             CHECK_THROWS_AS(json(json::value_t::string).get<json::object_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::boolean).get<json::object_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::object_t>(), std::logic_error);
+            CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::object_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::number_float).get<json::object_t>(), std::logic_error);
 
             CHECK_THROWS_WITH(json(json::value_t::null).get<json::object_t>(),
@@ -1689,6 +1800,8 @@ TEST_CASE("value conversion")
                               "type must be object, but is boolean");
             CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::object_t>(),
                               "type must be object, but is number");
+            CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::object_t>(),
+                              "type must be object, but is number");
             CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::object_t>(),
                               "type must be object, but is number");
         }
@@ -1732,7 +1845,7 @@ TEST_CASE("value conversion")
 
     SECTION("get an array (explicit)")
     {
-        json::array_t a_reference {json(1), json(2.2), json(false), json("string"), json()};
+        json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
         json j(a_reference);
 
         SECTION("json::array_t")
@@ -1772,6 +1885,7 @@ TEST_CASE("value conversion")
             CHECK_THROWS_AS(json(json::value_t::string).get<json::array_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::boolean).get<json::array_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::array_t>(), std::logic_error);
+            CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::array_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::number_float).get<json::array_t>(), std::logic_error);
 
             CHECK_THROWS_WITH(json(json::value_t::null).get<json::array_t>(),
@@ -1784,6 +1898,8 @@ TEST_CASE("value conversion")
                               "type must be array, but is boolean");
             CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::array_t>(),
                               "type must be array, but is number");
+            CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::array_t>(),
+                              "type must be array, but is number");
             CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::array_t>(),
                               "type must be array, but is number");
         }
@@ -1791,7 +1907,7 @@ TEST_CASE("value conversion")
 
     SECTION("get an array (implicit)")
     {
-        json::array_t a_reference {json(1), json(2.2), json(false), json("string"), json()};
+        json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
         json j(a_reference);
 
         SECTION("json::array_t")
@@ -1849,6 +1965,7 @@ TEST_CASE("value conversion")
             CHECK_THROWS_AS(json(json::value_t::array).get<json::string_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::boolean).get<json::string_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::string_t>(), std::logic_error);
+            CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::string_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::number_float).get<json::string_t>(), std::logic_error);
 
             CHECK_THROWS_WITH(json(json::value_t::null).get<json::string_t>(),
@@ -1861,6 +1978,8 @@ TEST_CASE("value conversion")
                               "type must be string, but is boolean");
             CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::string_t>(),
                               "type must be string, but is number");
+            CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::string_t>(),
+                              "type must be string, but is number");
             CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::string_t>(),
                               "type must be string, but is number");
         }
@@ -1908,6 +2027,7 @@ TEST_CASE("value conversion")
             CHECK_THROWS_AS(json(json::value_t::array).get<json::boolean_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::string).get<json::boolean_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::boolean_t>(), std::logic_error);
+            CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::boolean_t>(), std::logic_error);
             CHECK_THROWS_AS(json(json::value_t::number_float).get<json::boolean_t>(), std::logic_error);
 
             CHECK_THROWS_WITH(json(json::value_t::null).get<json::boolean_t>(),
@@ -1920,6 +2040,8 @@ TEST_CASE("value conversion")
                               "type must be boolean, but is string");
             CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::boolean_t>(),
                               "type must be boolean, but is number");
+            CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::boolean_t>(),
+                              "type must be boolean, but is number");
             CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::boolean_t>(),
                               "type must be boolean, but is number");
         }
@@ -1947,6 +2069,8 @@ TEST_CASE("value conversion")
     {
         json::number_integer_t n_reference {42};
         json j(n_reference);
+        json::number_unsigned_t n_unsigned_reference {42u};
+        json j_unsigned(n_unsigned_reference);
 
         SECTION("number_integer_t")
         {
@@ -1954,6 +2078,12 @@ TEST_CASE("value conversion")
             CHECK(json(n) == j);
         }
 
+        SECTION("number_unsigned_t")
+        {
+            json::number_unsigned_t n = j_unsigned.get<json::number_unsigned_t>();
+            CHECK(json(n) == j_unsigned);
+        }
+
         SECTION("short")
         {
             short n = j.get<short>();
@@ -2166,6 +2296,7 @@ TEST_CASE("value conversion")
                               "type must be number, but is boolean");
 
             CHECK_NOTHROW(json(json::value_t::number_float).get<json::number_integer_t>());
+            CHECK_NOTHROW(json(json::value_t::number_float).get<json::number_unsigned_t>());
         }
     }
 
@@ -2173,12 +2304,20 @@ TEST_CASE("value conversion")
     {
         json::number_integer_t n_reference {42};
         json j(n_reference);
+        json::number_unsigned_t n_unsigned_reference {42u};
+        json j_unsigned(n_unsigned_reference);
 
         SECTION("number_integer_t")
         {
             json::number_integer_t n = j.get<json::number_integer_t>();
             CHECK(json(n) == j);
         }
+        
+        SECTION("number_unsigned_t")
+        {
+            json::number_unsigned_t n = j_unsigned.get<json::number_unsigned_t>();
+            CHECK(json(n) == j_unsigned);
+        }
 
         SECTION("short")
         {
@@ -2188,8 +2327,8 @@ TEST_CASE("value conversion")
 
         SECTION("unsigned short")
         {
-            unsigned short n = j;
-            CHECK(json(n) == j);
+            unsigned short n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("int")
@@ -2200,8 +2339,8 @@ TEST_CASE("value conversion")
 
         SECTION("unsigned int")
         {
-            unsigned int n = j;
-            CHECK(json(n) == j);
+            unsigned int n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("long")
@@ -2212,8 +2351,8 @@ TEST_CASE("value conversion")
 
         SECTION("unsigned long")
         {
-            unsigned long n = j;
-            CHECK(json(n) == j);
+            unsigned long n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("long long")
@@ -2224,8 +2363,8 @@ TEST_CASE("value conversion")
 
         SECTION("unsigned long long")
         {
-            unsigned long long n = j;
-            CHECK(json(n) == j);
+            unsigned long long n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("int8_t")
@@ -2302,74 +2441,74 @@ TEST_CASE("value conversion")
 
         SECTION("uint8_t")
         {
-            uint8_t n = j;
-            CHECK(json(n) == j);
+            uint8_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint16_t")
         {
-            uint16_t n = j;
-            CHECK(json(n) == j);
+            uint16_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint32_t")
         {
-            uint32_t n = j;
-            CHECK(json(n) == j);
+            uint32_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint64_t")
         {
-            uint64_t n = j;
-            CHECK(json(n) == j);
+            uint64_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint8_fast_t")
         {
-            uint_fast8_t n = j;
-            CHECK(json(n) == j);
+            uint_fast8_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint16_fast_t")
         {
-            uint_fast16_t n = j;
-            CHECK(json(n) == j);
+            uint_fast16_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint32_fast_t")
         {
-            uint_fast32_t n = j;
-            CHECK(json(n) == j);
+            uint_fast32_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint64_fast_t")
         {
-            uint_fast64_t n = j;
-            CHECK(json(n) == j);
+            uint_fast64_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint8_least_t")
         {
-            uint_least8_t n = j;
-            CHECK(json(n) == j);
+            uint_least8_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint16_least_t")
         {
-            uint_least16_t n = j;
-            CHECK(json(n) == j);
+            uint_least16_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint32_least_t")
         {
-            uint_least32_t n = j;
-            CHECK(json(n) == j);
+            uint_least32_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
 
         SECTION("uint64_least_t")
         {
-            uint_least64_t n = j;
-            CHECK(json(n) == j);
+            uint_least64_t n = j_unsigned;
+            CHECK(json(n) == j_unsigned);
         }
     }
 
@@ -2416,6 +2555,7 @@ TEST_CASE("value conversion")
                               "type must be number, but is boolean");
 
             CHECK_NOTHROW(json(json::value_t::number_integer).get<json::number_float_t>());
+            CHECK_NOTHROW(json(json::value_t::number_unsigned).get<json::number_float_t>());
         }
     }
 
@@ -2448,43 +2588,48 @@ TEST_CASE("value conversion")
         SECTION("object-like STL containers")
         {
             json j1 = {{"one", 1}, {"two", 2}, {"three", 3}};
-            json j2 = {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}};
-            json j3 = {{"one", true}, {"two", false}, {"three", true}};
-            json j4 = {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}};
+            json j2 = {{"one", 1u}, {"two", 2u}, {"three", 3u}};
+            json j3 = {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}};
+            json j4 = {{"one", true}, {"two", false}, {"three", true}};
+            json j5 = {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}};
 
             SECTION("std::map")
             {
                 auto m1 = j1.get<std::map<std::string, int>>();
-                auto m2 = j2.get<std::map<std::string, double>>();
-                auto m3 = j3.get<std::map<std::string, bool>>();
-                //auto m4 = j4.get<std::map<std::string, std::string>>();
+                auto m2 = j2.get<std::map<std::string, unsigned int>>();
+                auto m3 = j3.get<std::map<std::string, double>>();
+                auto m4 = j4.get<std::map<std::string, bool>>();
+                //auto m5 = j5.get<std::map<std::string, std::string>>();
             }
 
             SECTION("std::unordered_map")
             {
                 auto m1 = j1.get<std::unordered_map<std::string, int>>();
-                auto m2 = j2.get<std::unordered_map<std::string, double>>();
-                auto m3 = j3.get<std::unordered_map<std::string, bool>>();
-                //auto m4 = j4.get<std::unordered_map<std::string, std::string>>();
-                //CHECK(m4["one"] == "eins");
+                auto m2 = j2.get<std::unordered_map<std::string, unsigned int>>();
+                auto m3 = j3.get<std::unordered_map<std::string, double>>();
+                auto m4 = j4.get<std::unordered_map<std::string, bool>>();
+                //auto m5 = j5.get<std::unordered_map<std::string, std::string>>();
+                //CHECK(m5["one"] == "eins");
             }
 
             SECTION("std::multimap")
             {
                 auto m1 = j1.get<std::multimap<std::string, int>>();
-                auto m2 = j2.get<std::multimap<std::string, double>>();
-                auto m3 = j3.get<std::multimap<std::string, bool>>();
-                //auto m4 = j4.get<std::multimap<std::string, std::string>>();
-                //CHECK(m4["one"] == "eins");
+                auto m2 = j2.get<std::multimap<std::string, unsigned int>>();
+                auto m3 = j3.get<std::multimap<std::string, double>>();
+                auto m4 = j4.get<std::multimap<std::string, bool>>();
+                //auto m5 = j5.get<std::multimap<std::string, std::string>>();
+                //CHECK(m5["one"] == "eins");
             }
 
             SECTION("std::unordered_multimap")
             {
                 auto m1 = j1.get<std::unordered_multimap<std::string, int>>();
-                auto m2 = j2.get<std::unordered_multimap<std::string, double>>();
-                auto m3 = j3.get<std::unordered_multimap<std::string, bool>>();
-                //auto m4 = j4.get<std::unordered_multimap<std::string, std::string>>();
-                //CHECK(m4["one"] == "eins");
+                auto m2 = j2.get<std::unordered_multimap<std::string, unsigned int>>();
+                auto m3 = j3.get<std::unordered_multimap<std::string, double>>();
+                auto m4 = j4.get<std::unordered_multimap<std::string, bool>>();
+                //auto m5 = j5.get<std::unordered_multimap<std::string, std::string>>();
+                //CHECK(m5["one"] == "eins");
             }
 
             SECTION("exception in case of a non-object type")
@@ -2497,56 +2642,63 @@ TEST_CASE("value conversion")
         SECTION("array-like STL containers")
         {
             json j1 = {1, 2, 3, 4};
-            json j2 = {1.2, 2.3, 3.4, 4.5};
-            json j3 = {true, false, true};
-            json j4 = {"one", "two", "three"};
+            json j2 = {1u, 2u, 3u, 4u};
+            json j3 = {1.2, 2.3, 3.4, 4.5};
+            json j4 = {true, false, true};
+            json j5 = {"one", "two", "three"};
 
             SECTION("std::list")
             {
                 auto m1 = j1.get<std::list<int>>();
-                auto m2 = j2.get<std::list<double>>();
-                auto m3 = j3.get<std::list<bool>>();
-                auto m4 = j4.get<std::list<std::string>>();
+                auto m2 = j2.get<std::list<unsigned int>>();
+                auto m3 = j3.get<std::list<double>>();
+                auto m4 = j4.get<std::list<bool>>();
+                auto m5 = j5.get<std::list<std::string>>();
             }
 
             //SECTION("std::forward_list")
             //{
             //    auto m1 = j1.get<std::forward_list<int>>();
-            //    auto m2 = j2.get<std::forward_list<double>>();
-            //    auto m3 = j3.get<std::forward_list<bool>>();
-            //    auto m4 = j4.get<std::forward_list<std::string>>();
+            //    auto m2 = j2.get<std::forward_list<unsigned int>>();
+            //    auto m3 = j3.get<std::forward_list<double>>();
+            //    auto m4 = j4.get<std::forward_list<bool>>();
+            //    auto m5 = j5.get<std::forward_list<std::string>>();
             //}
 
             SECTION("std::vector")
             {
                 auto m1 = j1.get<std::vector<int>>();
-                auto m2 = j2.get<std::vector<double>>();
-                auto m3 = j3.get<std::vector<bool>>();
-                auto m4 = j4.get<std::vector<std::string>>();
+                auto m2 = j2.get<std::vector<unsigned int>>();
+                auto m3 = j3.get<std::vector<double>>();
+                auto m4 = j4.get<std::vector<bool>>();
+                auto m5 = j5.get<std::vector<std::string>>();
             }
 
             SECTION("std::deque")
             {
                 auto m1 = j1.get<std::deque<int>>();
-                auto m2 = j2.get<std::deque<double>>();
-                auto m3 = j3.get<std::deque<bool>>();
-                auto m4 = j4.get<std::deque<std::string>>();
+                auto m2 = j2.get<std::deque<unsigned int>>();
+                auto m3 = j2.get<std::deque<double>>();
+                auto m4 = j4.get<std::deque<bool>>();
+                auto m5 = j5.get<std::deque<std::string>>();
             }
 
             SECTION("std::set")
             {
                 auto m1 = j1.get<std::set<int>>();
-                auto m2 = j2.get<std::set<double>>();
-                auto m3 = j3.get<std::set<bool>>();
-                auto m4 = j4.get<std::set<std::string>>();
+                auto m2 = j2.get<std::set<unsigned int>>();
+                auto m3 = j3.get<std::set<double>>();
+                auto m4 = j4.get<std::set<bool>>();
+                auto m5 = j5.get<std::set<std::string>>();
             }
 
             SECTION("std::unordered_set")
             {
                 auto m1 = j1.get<std::unordered_set<int>>();
-                auto m2 = j2.get<std::unordered_set<double>>();
-                auto m3 = j3.get<std::unordered_set<bool>>();
-                auto m4 = j4.get<std::unordered_set<std::string>>();
+                auto m2 = j2.get<std::unordered_set<unsigned int>>();
+                auto m3 = j3.get<std::unordered_set<double>>();
+                auto m4 = j4.get<std::unordered_set<bool>>();
+                auto m5 = j5.get<std::unordered_set<std::string>>();
             }
 
             SECTION("exception in case of a non-object type")
@@ -2574,6 +2726,7 @@ TEST_CASE("pointer access")
         {
             "number", {
                 {"integer", 42},
+                {"unsigned", 42u},
                 {"floating-point", 17.23}
             }
         },
@@ -2606,6 +2759,7 @@ TEST_CASE("pointer access")
         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_unsigned_t*>() == nullptr);
         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
     }
 
@@ -2649,6 +2803,7 @@ TEST_CASE("pointer access")
         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_unsigned_t*>() == nullptr);
         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
     }
 
@@ -2676,6 +2831,7 @@ TEST_CASE("pointer access")
         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_unsigned_t*>() == nullptr);
         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
     }
 
@@ -2703,6 +2859,7 @@ TEST_CASE("pointer access")
         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_unsigned_t*>() == nullptr);
         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
     }
 
@@ -2730,6 +2887,35 @@ TEST_CASE("pointer access")
         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_unsigned_t*>() == nullptr);
+        CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
+    }
+
+    SECTION("pointer access to number_unsigned_t")
+    {
+        using test_type = json::number_unsigned_t;
+        json value = 23u;
+
+        // 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_unsigned_t*>() != nullptr);
         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
     }
 
@@ -2757,6 +2943,7 @@ TEST_CASE("pointer access")
         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_unsigned_t*>() == nullptr);
         CHECK(value.get_ptr<json::number_float_t*>() != nullptr);
     }
 }
@@ -2935,7 +3122,7 @@ TEST_CASE("element access")
 {
     SECTION("array")
     {
-        json j = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+        json j = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
         const json j_const = j;
 
         SECTION("access specified element with bounds checking")
@@ -2943,29 +3130,31 @@ TEST_CASE("element access")
             SECTION("access within bounds")
             {
                 CHECK(j.at(0) == json(1));
-                CHECK(j.at(1) == json(true));
-                CHECK(j.at(2) == json(nullptr));
-                CHECK(j.at(3) == json("string"));
-                CHECK(j.at(4) == json(42.23));
-                CHECK(j.at(5) == json(json::object()));
-                CHECK(j.at(6) == json({1, 2, 3}));
+                CHECK(j.at(1) == json(1u));
+                CHECK(j.at(2) == json(true));
+                CHECK(j.at(3) == json(nullptr));
+                CHECK(j.at(4) == json("string"));
+                CHECK(j.at(5) == json(42.23));
+                CHECK(j.at(6) == json(json::object()));
+                CHECK(j.at(7) == json({1, 2, 3}));
 
                 CHECK(j_const.at(0) == json(1));
-                CHECK(j_const.at(1) == json(true));
-                CHECK(j_const.at(2) == json(nullptr));
-                CHECK(j_const.at(3) == json("string"));
-                CHECK(j_const.at(4) == json(42.23));
-                CHECK(j_const.at(5) == json(json::object()));
-                CHECK(j_const.at(6) == json({1, 2, 3}));
+                CHECK(j_const.at(1) == json(1u));
+                CHECK(j_const.at(2) == json(true));
+                CHECK(j_const.at(3) == json(nullptr));
+                CHECK(j_const.at(4) == json("string"));
+                CHECK(j_const.at(5) == json(42.23));
+                CHECK(j_const.at(6) == json(json::object()));
+                CHECK(j_const.at(7) == json({1, 2, 3}));
             }
 
             SECTION("access outside bounds")
             {
-                CHECK_THROWS_AS(j.at(7), std::out_of_range);
-                CHECK_THROWS_AS(j_const.at(7), std::out_of_range);
+                CHECK_THROWS_AS(j.at(8), std::out_of_range);
+                CHECK_THROWS_AS(j_const.at(8), std::out_of_range);
 
-                CHECK_THROWS_WITH(j.at(7), "array index 7 is out of range");
-                CHECK_THROWS_WITH(j_const.at(7), "array index 7 is out of range");
+                CHECK_THROWS_WITH(j.at(8), "array index 8 is out of range");
+                CHECK_THROWS_WITH(j_const.at(8), "array index 8 is out of range");
             }
 
             SECTION("access on non-array type")
@@ -3025,6 +3214,17 @@ TEST_CASE("element access")
                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number");
                 }
 
+                SECTION("number (unsigned)")
+                {
+                    json j_nonarray(json::value_t::number_unsigned);
+                    const json j_nonarray_const(j_nonarray);
+                    CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
+                    CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
+
+                    CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number");
+                    CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number");
+                }
+
                 SECTION("number (floating-point)")
                 {
                     json j_nonarray(json::value_t::number_float);
@@ -3051,20 +3251,22 @@ TEST_CASE("element access")
             SECTION("access within bounds")
             {
                 CHECK(j[0] == json(1));
-                CHECK(j[1] == json(true));
-                CHECK(j[2] == json(nullptr));
-                CHECK(j[3] == json("string"));
-                CHECK(j[4] == json(42.23));
-                CHECK(j[5] == json(json::object()));
-                CHECK(j[6] == json({1, 2, 3}));
+                CHECK(j[1] == json(1u));
+                CHECK(j[2] == json(true));
+                CHECK(j[3] == json(nullptr));
+                CHECK(j[4] == json("string"));
+                CHECK(j[5] == json(42.23));
+                CHECK(j[6] == json(json::object()));
+                CHECK(j[7] == json({1, 2, 3}));
 
                 CHECK(j_const[0] == json(1));
-                CHECK(j_const[1] == json(true));
-                CHECK(j_const[2] == json(nullptr));
-                CHECK(j_const[3] == json("string"));
-                CHECK(j_const[4] == json(42.23));
-                CHECK(j_const[5] == json(json::object()));
-                CHECK(j_const[6] == json({1, 2, 3}));
+                CHECK(j_const[1] == json(1u));
+                CHECK(j_const[2] == json(true));
+                CHECK(j_const[3] == json(nullptr));
+                CHECK(j_const[4] == json("string"));
+                CHECK(j_const[5] == json(42.23));
+                CHECK(j_const[6] == json(json::object()));
+                CHECK(j_const[7] == json({1, 2, 3}));
             }
 
             SECTION("access on non-array type")
@@ -3128,6 +3330,16 @@ TEST_CASE("element access")
                     CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number");
                 }
 
+                SECTION("number (unsigned)")
+                {
+                    json j_nonarray(json::value_t::number_unsigned);
+                    const json j_nonarray_const(j_nonarray);
+                    CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
+                    CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
+                    CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number");
+                    CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number");
+                }
+
                 SECTION("number (floating-point)")
                 {
                     json j_nonarray(json::value_t::number_float);
@@ -3145,44 +3357,49 @@ TEST_CASE("element access")
             SECTION("remove element by index")
             {
                 {
-                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                     jarray.erase(0);
-                    CHECK(jarray == json({true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
+                    CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
                 }
                 {
-                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                     jarray.erase(1);
-                    CHECK(jarray == json({1, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
+                    CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
                 }
                 {
-                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                     jarray.erase(2);
-                    CHECK(jarray == json({1, true, "string", 42.23, json::object(), {1, 2, 3}}));
+                    CHECK(jarray == json({1, 1u, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
                 }
                 {
-                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                     jarray.erase(3);
-                    CHECK(jarray == json({1, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
+                    CHECK(jarray == json({1, 1u, true, "string", 42.23, json::object(), {1, 2, 3}}));
                 }
                 {
-                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                     jarray.erase(4);
-                    CHECK(jarray == json({1, true, nullptr, "string", json::object(), {1, 2, 3}}));
+                    CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
                 }
                 {
-                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                     jarray.erase(5);
-                    CHECK(jarray == json({1, true, nullptr, "string", 42.23, {1, 2, 3}}));
+                    CHECK(jarray == json({1, 1u, true, nullptr, "string", json::object(), {1, 2, 3}}));
                 }
                 {
-                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                     jarray.erase(6);
-                    CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object()}));
+                    CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, {1, 2, 3}}));
                 }
                 {
-                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
-                    CHECK_THROWS_AS(jarray.erase(7), std::out_of_range);
-                    CHECK_THROWS_WITH(jarray.erase(7), "index out of range");
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    jarray.erase(7);
+                    CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object()}));
+                }
+                {
+                    json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                    CHECK_THROWS_AS(jarray.erase(8), std::out_of_range);
+                    CHECK_THROWS_WITH(jarray.erase(8), "index out of range");
                 }
             }
 
@@ -3191,29 +3408,29 @@ TEST_CASE("element access")
                 SECTION("erase(begin())")
                 {
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                         json::iterator it2 = jarray.erase(jarray.begin());
-                        CHECK(jarray == json({true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
-                        CHECK(*it2 == json(true));
+                        CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
+                        CHECK(*it2 == json(1u));
                     }
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                         json::const_iterator it2 = jarray.erase(jarray.cbegin());
-                        CHECK(jarray == json({true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
-                        CHECK(*it2 == json(true));
+                        CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
+                        CHECK(*it2 == json(1u));
                     }
                 }
 
                 SECTION("erase(begin(), end())")
                 {
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                         json::iterator it2 = jarray.erase(jarray.begin(), jarray.end());
                         CHECK(jarray == json::array());
                         CHECK(it2 == jarray.end());
                     }
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                         json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cend());
                         CHECK(jarray == json::array());
                         CHECK(it2 == jarray.cend());
@@ -3223,15 +3440,15 @@ TEST_CASE("element access")
                 SECTION("erase(begin(), begin())")
                 {
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                         json::iterator it2 = jarray.erase(jarray.begin(), jarray.begin());
-                        CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
+                        CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
                         CHECK(*it2 == json(1));
                     }
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                         json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cbegin());
-                        CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
+                        CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
                         CHECK(*it2 == json(1));
                     }
                 }
@@ -3239,17 +3456,17 @@ TEST_CASE("element access")
                 SECTION("erase at offset")
                 {
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
-                        json::iterator it = jarray.begin() + 3;
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json::iterator it = jarray.begin() + 4;
                         json::iterator it2 = jarray.erase(it);
-                        CHECK(jarray == json({1, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
+                        CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
                         CHECK(*it2 == json(42.23));
                     }
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
-                        json::const_iterator it = jarray.cbegin() + 3;
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json::const_iterator it = jarray.cbegin() + 4;
                         json::const_iterator it2 = jarray.erase(it);
-                        CHECK(jarray == json({1, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
+                        CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
                         CHECK(*it2 == json(42.23));
                     }
                 }
@@ -3257,15 +3474,15 @@ TEST_CASE("element access")
                 SECTION("erase subrange")
                 {
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
-                        json::iterator it2 = jarray.erase(jarray.begin() + 2, jarray.begin() + 5);
-                        CHECK(jarray == json({1, true, json::object(), {1, 2, 3}}));
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json::iterator it2 = jarray.erase(jarray.begin() + 3, jarray.begin() + 6);
+                        CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
                         CHECK(*it2 == json::object());
                     }
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
-                        json::const_iterator it2 = jarray.erase(jarray.cbegin() + 2, jarray.cbegin() + 5);
-                        CHECK(jarray == json({1, true, json::object(), {1, 2, 3}}));
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json::const_iterator it2 = jarray.erase(jarray.cbegin() + 3, jarray.cbegin() + 6);
+                        CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
                         CHECK(*it2 == json::object());
                     }
                 }
@@ -3273,7 +3490,7 @@ TEST_CASE("element access")
                 SECTION("different arrays")
                 {
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                         json jarray2 = {"foo", "bar"};
                         CHECK_THROWS_AS(jarray.erase(jarray2.begin()), std::domain_error);
                         CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), std::domain_error);
@@ -3289,7 +3506,7 @@ TEST_CASE("element access")
                                           "iterators do not fit current value");
                     }
                     {
-                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
+                        json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
                         json jarray2 = {"foo", "bar"};
                         CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), std::domain_error);
                         CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), std::domain_error);
@@ -3344,6 +3561,13 @@ TEST_CASE("element access")
                     CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number");
                 }
 
+                SECTION("number (unsigned)")
+                {
+                    json j_nonobject(json::value_t::number_unsigned);
+                    CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
+                    CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number");
+                }
+
                 SECTION("number (floating-point)")
                 {
                     json j_nonobject(json::value_t::number_float);
@@ -3356,7 +3580,7 @@ TEST_CASE("element access")
 
     SECTION("object")
     {
-        json j = {{"integer", 1}, {"floating", 42.23}, {"null", nullptr}, {"string", "hello world"}, {"boolean", true}, {"object", json::object()}, {"array", {1, 2, 3}}};
+        json j = {{"integer", 1}, {"unsigned", 1u}, {"floating", 42.23}, {"null", nullptr}, {"string", "hello world"}, {"boolean", true}, {"object", json::object()}, {"array", {1, 2, 3}}};
         const json j_const = j;
 
         SECTION("access specified element with bounds checking")
@@ -3364,6 +3588,7 @@ TEST_CASE("element access")
             SECTION("access within bounds")
             {
                 CHECK(j.at("integer") == json(1));
+                CHECK(j.at("unsigned") == json(1u));
                 CHECK(j.at("boolean") == json(true));
                 CHECK(j.at("null") == json(nullptr));
                 CHECK(j.at("string") == json("hello world"));
@@ -3372,6 +3597,7 @@ TEST_CASE("element access")
                 CHECK(j.at("array") == json({1, 2, 3}));
 
                 CHECK(j_const.at("integer") == json(1));
+                CHECK(j_const.at("unsigned") == json(1u));
                 CHECK(j_const.at("boolean") == json(true));
                 CHECK(j_const.at("null") == json(nullptr));
                 CHECK(j_const.at("string") == json("hello world"));
@@ -3439,7 +3665,17 @@ TEST_CASE("element access")
                     CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
                     CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
                 }
-
+                
+                SECTION("number (unsigned)")
+                {
+                    json j_nonobject(json::value_t::number_unsigned);
+                    const json j_nonobject_const(j_nonobject);
+                    CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
+                    CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
+                    CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
+                    CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
+                }
+                
                 SECTION("number (floating-point)")
                 {
                     json j_nonobject(json::value_t::number_float);
@@ -3458,6 +3694,8 @@ TEST_CASE("element access")
             {
                 CHECK(j.value("integer", 2) == 1);
                 CHECK(j.value("integer", 1.0) == Approx(1));
+                CHECK(j.value("unsigned", 2) == 1u);
+                CHECK(j.value("unsigned", 1.0) == Approx(1u));
                 CHECK(j.value("null", json(1)) == json());
                 CHECK(j.value("boolean", false) == true);
                 CHECK(j.value("string", "bar") == "hello world");
@@ -3469,6 +3707,8 @@ TEST_CASE("element access")
 
                 CHECK(j_const.value("integer", 2) == 1);
                 CHECK(j_const.value("integer", 1.0) == Approx(1));
+                CHECK(j_const.value("unsigned", 2) == 1u);
+                CHECK(j_const.value("unsigned", 1.0) == Approx(1u));
                 CHECK(j_const.value("boolean", false) == true);
                 CHECK(j_const.value("string", "bar") == "hello world");
                 CHECK(j_const.value("string", std::string("bar")) == "hello world");
@@ -3481,6 +3721,7 @@ TEST_CASE("element access")
             SECTION("access non-existing value")
             {
                 CHECK(j.value("_", 2) == 2);
+                CHECK(j.value("_", 2u) == 2u);
                 CHECK(j.value("_", false) == false);
                 CHECK(j.value("_", "bar") == "bar");
                 CHECK(j.value("_", 12.34) == Approx(12.34));
@@ -3488,6 +3729,7 @@ TEST_CASE("element access")
                 CHECK(j.value("_", json({10, 100})) == json({10, 100}));
 
                 CHECK(j_const.value("_", 2) == 2);
+                CHECK(j_const.value("_", 2u) == 2u);
                 CHECK(j_const.value("_", false) == false);
                 CHECK(j_const.value("_", "bar") == "bar");
                 CHECK(j_const.value("_", 12.34) == Approx(12.34));
@@ -3547,6 +3789,16 @@ TEST_CASE("element access")
                     CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number");
                 }
 
+                SECTION("number (unsigned)")
+                {
+                    json j_nonobject(json::value_t::number_unsigned);
+                    const json j_nonobject_const(j_nonobject);
+                    CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
+                    CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
+                    CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number");
+                    CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number");
+                }
+
                 SECTION("number (floating-point)")
                 {
                     json j_nonobject(json::value_t::number_float);
@@ -3564,9 +3816,9 @@ TEST_CASE("element access")
             // "array" is the smallest key
             CHECK(j.front() == json({1, 2, 3}));
             CHECK(j_const.front() == json({1, 2, 3}));
-            // "string" is the largest key
-            CHECK(j.back() == json("hello world"));
-            CHECK(j_const.back() == json("hello world"));
+            // "unsigned" is the largest key
+            CHECK(j.back() == json(1u));
+            CHECK(j_const.back() == json(1u));
         }
 
         SECTION("access specified element")
@@ -3576,6 +3828,9 @@ TEST_CASE("element access")
                 CHECK(j["integer"] == json(1));
                 CHECK(j[json::object_t::key_type("integer")] == j["integer"]);
 
+                CHECK(j["unsigned"] == json(1u));
+                CHECK(j[json::object_t::key_type("unsigned")] == j["unsigned"]);
+
                 CHECK(j["boolean"] == json(true));
                 CHECK(j[json::object_t::key_type("boolean")] == j["boolean"]);
 
@@ -3695,6 +3950,22 @@ TEST_CASE("element access")
                                       "cannot use operator[] with number");
                 }
 
+                SECTION("number (unsigned)")
+                {
+                    json j_nonobject(json::value_t::number_unsigned);
+                    const json j_const_nonobject(j_nonobject);
+                    CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
+                    CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
+                    CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
+                    CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
+                    CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number");
+                    CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
+                                      "cannot use operator[] with number");
+                    CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number");
+                    CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
+                                      "cannot use operator[] with number");
+                }
+
                 SECTION("number (floating-point)")
                 {
                     json j_nonobject(json::value_t::number_float);
@@ -3722,6 +3993,11 @@ TEST_CASE("element access")
                 CHECK(j.find("integer") == j.end());
                 CHECK(j.erase("integer") == 0);
 
+                CHECK(j.find("unsigned") != j.end());
+                CHECK(j.erase("unsigned") == 1);
+                CHECK(j.find("unsigned") == j.end());
+                CHECK(j.erase("unsigned") == 0);
+
                 CHECK(j.find("boolean") != j.end());
                 CHECK(j.erase("boolean") == 1);
                 CHECK(j.find("boolean") == j.end());
@@ -3758,15 +4034,15 @@ TEST_CASE("element access")
                 SECTION("erase(begin())")
                 {
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         json::iterator it2 = jobject.erase(jobject.begin());
-                        CHECK(jobject == json({{"b", 1}, {"c", 17}}));
+                        CHECK(jobject == json({{"b", 1}, {"c", 17u}}));
                         CHECK(*it2 == json(1));
                     }
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         json::const_iterator it2 = jobject.erase(jobject.cbegin());
-                        CHECK(jobject == json({{"b", 1}, {"c", 17}}));
+                        CHECK(jobject == json({{"b", 1}, {"c", 17u}}));
                         CHECK(*it2 == json(1));
                     }
                 }
@@ -3774,13 +4050,13 @@ TEST_CASE("element access")
                 SECTION("erase(begin(), end())")
                 {
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         json::iterator it2 = jobject.erase(jobject.begin(), jobject.end());
                         CHECK(jobject == json::object());
                         CHECK(it2 == jobject.end());
                     }
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cend());
                         CHECK(jobject == json::object());
                         CHECK(it2 == jobject.cend());
@@ -3790,15 +4066,15 @@ TEST_CASE("element access")
                 SECTION("erase(begin(), begin())")
                 {
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         json::iterator it2 = jobject.erase(jobject.begin(), jobject.begin());
-                        CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17}}));
+                        CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
                         CHECK(*it2 == json("a"));
                     }
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cbegin());
-                        CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17}}));
+                        CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
                         CHECK(*it2 == json("a"));
                     }
                 }
@@ -3806,17 +4082,17 @@ TEST_CASE("element access")
                 SECTION("erase at offset")
                 {
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         json::iterator it = jobject.find("b");
                         json::iterator it2 = jobject.erase(it);
-                        CHECK(jobject == json({{"a", "a"}, {"c", 17}}));
+                        CHECK(jobject == json({{"a", "a"}, {"c", 17u}}));
                         CHECK(*it2 == json(17));
                     }
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         json::const_iterator it = jobject.find("b");
                         json::const_iterator it2 = jobject.erase(it);
-                        CHECK(jobject == json({{"a", "a"}, {"c", 17}}));
+                        CHECK(jobject == json({{"a", "a"}, {"c", 17u}}));
                         CHECK(*it2 == json(17));
                     }
                 }
@@ -3824,13 +4100,13 @@ TEST_CASE("element access")
                 SECTION("erase subrange")
                 {
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
                         json::iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
                         CHECK(jobject == json({{"a", "a"}, {"e", true}}));
                         CHECK(*it2 == json(true));
                     }
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
                         json::const_iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
                         CHECK(jobject == json({{"a", "a"}, {"e", true}}));
                         CHECK(*it2 == json(true));
@@ -3840,8 +4116,8 @@ TEST_CASE("element access")
                 SECTION("different objects")
                 {
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
-                        json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
+                        json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         CHECK_THROWS_AS(jobject.erase(jobject2.begin()), std::domain_error);
                         CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), std::domain_error);
                         CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), std::domain_error);
@@ -3855,8 +4131,8 @@ TEST_CASE("element access")
                                           "iterators do not fit current value");
                     }
                     {
-                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
-                        json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17}};
+                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
+                        json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
                         CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), std::domain_error);
                         CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), std::domain_error);
                         CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), std::domain_error);
@@ -3923,7 +4199,7 @@ TEST_CASE("element access")
             SECTION("existing element")
             {
                 for (auto key :
-                        {"integer", "floating", "null", "string", "boolean", "object", "array"
+                        {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
                         })
                 {
                     CHECK(j.find(key) != j.end());
@@ -3989,6 +4265,14 @@ TEST_CASE("element access")
                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
                 }
 
+                SECTION("number (unsigned)")
+                {
+                    json j_nonarray(json::value_t::number_unsigned);
+                    const json j_nonarray_const(j_nonarray);
+                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
+                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
+                }
+
                 SECTION("number (floating-point)")
                 {
                     json j_nonarray(json::value_t::number_float);
@@ -4004,7 +4288,7 @@ TEST_CASE("element access")
             SECTION("existing element")
             {
                 for (auto key :
-                        {"integer", "floating", "null", "string", "boolean", "object", "array"
+                        {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
                         })
                 {
                     CHECK(j.count(key) == 1);
@@ -4068,6 +4352,14 @@ TEST_CASE("element access")
                     CHECK(j_nonobject_const.count("foo") == 0);
                 }
 
+                SECTION("number (unsigned)")
+                {
+                    json j_nonobject(json::value_t::number_unsigned);
+                    const json j_nonobject_const(j_nonobject);
+                    CHECK(j_nonobject.count("foo") == 0);
+                    CHECK(j_nonobject_const.count("foo") == 0);
+                }
+
                 SECTION("number (floating-point)")
                 {
                     json j_nonobject(json::value_t::number_float);
@@ -4143,6 +4435,20 @@ TEST_CASE("element access")
                 }
             }
 
+            SECTION("number (unsigned)")
+            {
+                {
+                    json j = 17u;
+                    CHECK(j.front() == j);
+                    CHECK(j.back() == j);
+                }
+                {
+                    const json j = 17u;
+                    CHECK(j.front() == j);
+                    CHECK(j.back() == j);
+                }
+            }
+
             SECTION("number (floating point)")
             {
                 {
@@ -4222,6 +4528,22 @@ TEST_CASE("element access")
                 }
             }
 
+            SECTION("number (unsigned)")
+            {
+                {
+                    json j = 17u;
+                    json::iterator it = j.erase(j.begin());
+                    CHECK(j.type() == json::value_t::null);
+                    CHECK(it == j.end());
+                }
+                {
+                    json j = 17u;
+                    json::const_iterator it = j.erase(j.cbegin());
+                    CHECK(j.type() == json::value_t::null);
+                    CHECK(it == j.end());
+                }
+            }
+
             SECTION("number (floating point)")
             {
                 {
@@ -4283,6 +4605,20 @@ TEST_CASE("element access")
                 }
             }
 
+            SECTION("number (unsigned)")
+            {
+                {
+                    json j = 17u;
+                    CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
+                    CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
+                }
+                {
+                    json j = 17u;
+                    CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
+                    CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
+                }
+            }
+
             SECTION("number (floating point)")
             {
                 {
@@ -4362,6 +4698,22 @@ TEST_CASE("element access")
                 }
             }
 
+            SECTION("number (unsigned)")
+            {
+                {
+                    json j = 17u;
+                    json::iterator it = j.erase(j.begin(), j.end());
+                    CHECK(j.type() == json::value_t::null);
+                    CHECK(it == j.end());
+                }
+                {
+                    json j = 17u;
+                    json::const_iterator it = j.erase(j.cbegin(), j.cend());
+                    CHECK(j.type() == json::value_t::null);
+                    CHECK(it == j.end());
+                }
+            }
+
             SECTION("number (floating point)")
             {
                 {
@@ -4435,6 +4787,24 @@ TEST_CASE("element access")
                 }
             }
 
+            SECTION("number (unsigned)")
+            {
+                {
+                    json j = 17u;
+                    CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
+                    CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
+                    CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
+                    CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
+                }
+                {
+                    json j = 17u;
+                    CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
+                    CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
+                    CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
+                    CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
+                }
+            }
+
             SECTION("number (floating point)")
             {
                 {
@@ -5065,7 +5435,7 @@ TEST_CASE("iterators")
 
         SECTION("object")
         {
-            json j = {{"A", 1}, {"B", 2}, {"C", 3}};
+            json j = {{"A", 1},{"B", 2},{"C", 3}};
             json j_const(j);
 
             SECTION("json + begin/end")
@@ -5451,6 +5821,210 @@ TEST_CASE("iterators")
             }
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j = 23u;
+            json j_const(j);
+
+            SECTION("json + begin/end")
+            {
+                json::iterator it = j.begin();
+                CHECK(it != j.end());
+                CHECK(*it == j);
+
+                it++;
+                CHECK(it != j.begin());
+                CHECK(it == j.end());
+
+                it--;
+                CHECK(it == j.begin());
+                CHECK(it != j.end());
+                CHECK(*it == j);
+
+                ++it;
+                CHECK(it != j.begin());
+                CHECK(it == j.end());
+
+                --it;
+                CHECK(it == j.begin());
+                CHECK(it != j.end());
+                CHECK(*it == j);
+            }
+
+            SECTION("const json + begin/end")
+            {
+                json::const_iterator it = j_const.begin();
+                CHECK(it != j_const.end());
+                CHECK(*it == j_const);
+
+                it++;
+                CHECK(it != j_const.begin());
+                CHECK(it == j_const.end());
+
+                it--;
+                CHECK(it == j_const.begin());
+                CHECK(it != j_const.end());
+                CHECK(*it == j_const);
+
+                ++it;
+                CHECK(it != j_const.begin());
+                CHECK(it == j_const.end());
+
+                --it;
+                CHECK(it == j_const.begin());
+                CHECK(it != j_const.end());
+                CHECK(*it == j_const);
+            }
+
+            SECTION("json + cbegin/cend")
+            {
+                json::const_iterator it = j.cbegin();
+                CHECK(it != j.cend());
+                CHECK(*it == j);
+
+                it++;
+                CHECK(it != j.cbegin());
+                CHECK(it == j.cend());
+
+                it--;
+                CHECK(it == j.cbegin());
+                CHECK(it != j.cend());
+                CHECK(*it == j);
+
+                ++it;
+                CHECK(it != j.cbegin());
+                CHECK(it == j.cend());
+
+                --it;
+                CHECK(it == j.cbegin());
+                CHECK(it != j.cend());
+                CHECK(*it == j);
+            }
+
+            SECTION("const json + cbegin/cend")
+            {
+                json::const_iterator it = j_const.cbegin();
+                CHECK(it != j_const.cend());
+                CHECK(*it == j_const);
+
+                it++;
+                CHECK(it != j_const.cbegin());
+                CHECK(it == j_const.cend());
+
+                it--;
+                CHECK(it == j_const.cbegin());
+                CHECK(it != j_const.cend());
+                CHECK(*it == j_const);
+
+                ++it;
+                CHECK(it != j_const.cbegin());
+                CHECK(it == j_const.cend());
+
+                --it;
+                CHECK(it == j_const.cbegin());
+                CHECK(it != j_const.cend());
+                CHECK(*it == j_const);
+            }
+
+            SECTION("json + rbegin/rend")
+            {
+                json::reverse_iterator it = j.rbegin();
+                CHECK(it != j.rend());
+                CHECK(*it == j);
+
+                it++;
+                CHECK(it != j.rbegin());
+                CHECK(it == j.rend());
+
+                it--;
+                CHECK(it == j.rbegin());
+                CHECK(it != j.rend());
+                CHECK(*it == j);
+
+                ++it;
+                CHECK(it != j.rbegin());
+                CHECK(it == j.rend());
+
+                --it;
+                CHECK(it == j.rbegin());
+                CHECK(it != j.rend());
+                CHECK(*it == j);
+            }
+
+            SECTION("json + crbegin/crend")
+            {
+                json::const_reverse_iterator it = j.crbegin();
+                CHECK(it != j.crend());
+                CHECK(*it == j);
+
+                it++;
+                CHECK(it != j.crbegin());
+                CHECK(it == j.crend());
+
+                it--;
+                CHECK(it == j.crbegin());
+                CHECK(it != j.crend());
+                CHECK(*it == j);
+
+                ++it;
+                CHECK(it != j.crbegin());
+                CHECK(it == j.crend());
+
+                --it;
+                CHECK(it == j.crbegin());
+                CHECK(it != j.crend());
+                CHECK(*it == j);
+            }
+
+            SECTION("const json + crbegin/crend")
+            {
+                json::const_reverse_iterator it = j_const.crbegin();
+                CHECK(it != j_const.crend());
+                CHECK(*it == j_const);
+
+                it++;
+                CHECK(it != j_const.crbegin());
+                CHECK(it == j_const.crend());
+
+                it--;
+                CHECK(it == j_const.crbegin());
+                CHECK(it != j_const.crend());
+                CHECK(*it == j_const);
+
+                ++it;
+                CHECK(it != j_const.crbegin());
+                CHECK(it == j_const.crend());
+
+                --it;
+                CHECK(it == j_const.crbegin());
+                CHECK(it != j_const.crend());
+                CHECK(*it == j_const);
+            }
+
+            SECTION("key/value")
+            {
+                auto it = j.begin();
+                auto cit = j_const.cbegin();
+                CHECK_THROWS_AS(it.key(), std::domain_error);
+                CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators");
+                CHECK(it.value() == json(23));
+                CHECK_THROWS_AS(cit.key(), std::domain_error);
+                CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators");
+                CHECK(cit.value() == json(23));
+
+                auto rit = j.rend();
+                auto crit = j.crend();
+                CHECK_THROWS_AS(rit.key(), std::domain_error);
+                CHECK_THROWS_AS(rit.value(), std::out_of_range);
+                CHECK_THROWS_AS(crit.key(), std::domain_error);
+                CHECK_THROWS_AS(crit.value(), std::out_of_range);
+                CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators");
+                CHECK_THROWS_WITH(rit.value(), "cannot get value");
+                CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators");
+                CHECK_THROWS_WITH(crit.value(), "cannot get value");
+            }
+        }
+
         SECTION("number (float)")
         {
             json j = 23.42;
@@ -5734,7 +6308,7 @@ TEST_CASE("iterators")
 
     SECTION("iterator comparisons")
     {
-        json j_values = {nullptr, true, 42, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
+        json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
 
         for (json& j : j_values)
         {
@@ -6153,7 +6727,7 @@ TEST_CASE("iterators")
 
     SECTION("reverse iterator comparisons")
     {
-        json j_values = {nullptr, true, 42, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
+        json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
 
         for (json& j : j_values)
         {
@@ -6707,6 +7281,24 @@ TEST_CASE("capacity")
             }
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j = 23u;
+            json j_const(j);
+
+            SECTION("result of empty")
+            {
+                CHECK(j.empty() == false);
+                CHECK(j_const.empty() == false);
+            }
+
+            SECTION("definition of empty")
+            {
+                CHECK(j.begin() != j.end());
+                CHECK(j_const.begin() != j_const.end());
+            }
+        }
+
         SECTION("number (float)")
         {
             json j = 23.42;
@@ -6892,6 +7484,26 @@ TEST_CASE("capacity")
             }
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j = 23u;
+            json j_const(j);
+
+            SECTION("result of size")
+            {
+                CHECK(j.size() == 1);
+                CHECK(j_const.size() == 1);
+            }
+
+            SECTION("definition of size")
+            {
+                CHECK(std::distance(j.begin(), j.end()) == j.size());
+                CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
+                CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
+                CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
+            }
+        }
+
         SECTION("number (float)")
         {
             json j = 23.42;
@@ -7025,6 +7637,18 @@ TEST_CASE("capacity")
             }
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j = 23u;
+            json j_const(j);
+
+            SECTION("result of max_size")
+            {
+                CHECK(j.max_size() == 1);
+                CHECK(j_const.max_size() == 1);
+            }
+        }
+
         SECTION("number (float)")
         {
             json j = 23.42;
@@ -7121,6 +7745,14 @@ TEST_CASE("modifiers")
             CHECK(j == json(json::value_t::number_integer));
         }
 
+        SECTION("number (unsigned)")
+        {
+            json j = 23u;
+
+            j.clear();
+            CHECK(j == json(json::value_t::number_integer));
+        }
+
         SECTION("number (float)")
         {
             json j = 23.42;
@@ -7661,6 +8293,7 @@ TEST_CASE("lexicographical comparison operators")
             json::value_t::null,
             json::value_t::boolean,
             json::value_t::number_integer,
+            json::value_t::number_unsigned,
             json::value_t::number_float,
             json::value_t::object,
             json::value_t::array,
@@ -7671,13 +8304,14 @@ TEST_CASE("lexicographical comparison operators")
         {
             std::vector<std::vector<bool>> expected =
             {
-                {false, true, true, true, true, true, true},
-                {false, false, true, true, true, true, true},
-                {false, false, false, false, true, true, true},
-                {false, false, false, false, true, true, true},
-                {false, false, false, false, false, true, true},
-                {false, false, false, false, false, false, true},
-                {false, false, false, false, false, false, false}
+                {false, true, true, true, true, true, true, true},
+                {false, false, true, true, true, true, true, true},
+                {false, false, false, false, false, true, true, true},
+                {false, false, false, false, false, true, true, true},
+                {false, false, false, false, false, true, true, true},
+                {false, false, false, false, false, false, true, true},
+                {false, false, false, false, false, false, false, true},
+                {false, false, false, false, false, false, false, false}
             };
 
             for (size_t i = 0; i < j_types.size(); ++i)
@@ -7699,6 +8333,7 @@ TEST_CASE("lexicographical comparison operators")
         {
             nullptr, nullptr,
             17, 42,
+            8u, 13u,
             3.14159, 23.42,
             "foo", "bar",
             true, false,
@@ -7710,26 +8345,30 @@ TEST_CASE("lexicographical comparison operators")
         {
             std::vector<std::vector<bool>> expected =
             {
-                {true, true, false, false, false, false, false, false, false, false, false, false, false, false},
-                {true, true, false, false, false, false, false, false, false, false, false, false, false, false},
-                {false, false, true, false, false, false, false, false, false, false, false, false, false, false},
-                {false, false, false, true, false, false, false, false, false, false, false, false, false, false},
-                {false, false, false, false, true, false, false, false, false, false, false, false, false, false},
-                {false, false, false, false, false, true, false, false, false, false, false, false, false, false},
-                {false, false, false, false, false, false, true, false, false, false, false, false, false, false},
-                {false, false, false, false, false, false, false, true, false, false, false, false, false, false},
-                {false, false, false, false, false, false, false, false, true, false, false, false, false, false},
-                {false, false, false, false, false, false, false, false, false, true, false, false, false, false},
-                {false, false, false, false, false, false, false, false, false, false, true, false, false, false},
-                {false, false, false, false, false, false, false, false, false, false, false, true, false, false},
-                {false, false, false, false, false, false, false, false, false, false, false, false, true, false},
-                {false, false, false, false, false, false, false, false, false, false, false, false, false, true}
+                {true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
+                {true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
+                {false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false},
+                {false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false},
+                {false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false},
+                {false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false},
+                {false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false},
+                {false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false},
+                {false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false},
+                {false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false},
+                {false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false},
+                {false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false},
+                {false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false},
+                {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false},
+                {false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false},
+                {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true}
             };
 
             for (size_t i = 0; i < j_values.size(); ++i)
             {
                 for (size_t j = 0; j < j_values.size(); ++j)
                 {
+                    CAPTURE(i);
+                    CAPTURE(j);
                     // check precomputed values
                     CHECK( (j_values[i] == j_values[j]) == expected[i][j] );
                 }
@@ -7756,6 +8395,8 @@ TEST_CASE("lexicographical comparison operators")
             {
                 for (size_t j = 0; j < j_values.size(); ++j)
                 {
+                    CAPTURE(i);
+                    CAPTURE(j);
                     // check definition
                     CHECK( (j_values[i] != j_values[j]) == not(j_values[i] == j_values[j]) );
                 }
@@ -7773,26 +8414,30 @@ TEST_CASE("lexicographical comparison operators")
         {
             std::vector<std::vector<bool>> expected =
             {
-                {false, false, true, true, true, true, true, true, true, true, true, true, true, true},
-                {false, false, true, true, true, true, true, true, true, true, true, true, true, true},
-                {false, false, false, true, false, true, true, true, false, false, true, true, true, true},
-                {false, false, false, false, false, false, true, true, false, false, true, true, true, true},
-                {false, false, true, true, false, true, true, true, false, false, true, true, true, true},
-                {false, false, false, true, false, false, true, true, false, false, true, true, true, true},
-                {false, false, false, false, false, false, false, false, false, false, false, false, false, false},
-                {false, false, false, false, false, false, true, false, false, false, false, false, false, false},
-                {false, false, true, true, true, true, true, true, false, false, true, true, true, true},
-                {false, false, true, true, true, true, true, true, true, false, true, true, true, true},
-                {false, false, false, false, false, false, true, true, false, false, false, true, false, false},
-                {false, false, false, false, false, false, true, true, false, false, false, false, false, false},
-                {false, false, false, false, false, false, true, true, false, false, true, true, false, false},
-                {false, false, false, false, false, false, true, true, false, false, true, true, true, false}
+                {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
+                {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
+                {false, false, false, true, false, false, false, true, true, true, false, false, true, true, true, true},
+                {false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, true},
+                {false, false, true, true, false, true, false, true, true, true, false, false, true, true, true, true},
+                {false, false, true, true, false, false, false, true, true, true, false, false, true, true, true, true},
+                {false, false, true, true, true, true, false, true, true, true, false, false, true, true, true, true},
+                {false, false, false, true, false, false, false, false, true, true, false, false, true, true, true, true},
+                {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
+                {false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false},
+                {false, false, true, true, true, true, true, true, true, true, false, false, true, true, true, true},
+                {false, false, true, true, true, true, true, true, true, true, true, false, true, true, true, true},
+                {false, false, false, false, false, false, false, false, true, true, false, false, false, true, false, false},
+                {false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false},
+                {false, false, false, false, false, false, false, false, true, true, false, false, true, true, false, false},
+                {false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, false}
             };
 
             for (size_t i = 0; i < j_values.size(); ++i)
             {
                 for (size_t j = 0; j < j_values.size(); ++j)
                 {
+                    CAPTURE(i);
+                    CAPTURE(j);
                     // check precomputed values
                     CHECK( (j_values[i] < j_values[j]) == expected[i][j] );
                 }
@@ -7802,6 +8447,7 @@ TEST_CASE("lexicographical comparison operators")
             json j_discarded(json::value_t::discarded);
             for (size_t i = 0; i < j_values.size(); ++i)
             {
+                CAPTURE(i);
                 CHECK( (j_values[i] < j_discarded) == false);
                 CHECK( (j_discarded < j_values[i]) == false);
                 CHECK( (j_discarded < j_discarded) == false);
@@ -7814,6 +8460,8 @@ TEST_CASE("lexicographical comparison operators")
             {
                 for (size_t j = 0; j < j_values.size(); ++j)
                 {
+                    CAPTURE(i);
+                    CAPTURE(j);
                     // check definition
                     CHECK( (j_values[i] <= j_values[j]) == not(j_values[j] < j_values[i]) );
                 }
@@ -7826,6 +8474,8 @@ TEST_CASE("lexicographical comparison operators")
             {
                 for (size_t j = 0; j < j_values.size(); ++j)
                 {
+                    CAPTURE(i);
+                    CAPTURE(j);
                     // check definition
                     CHECK( (j_values[i] > j_values[j]) == (j_values[j] < j_values[i]) );
                 }
@@ -7838,6 +8488,8 @@ TEST_CASE("lexicographical comparison operators")
             {
                 for (size_t j = 0; j < j_values.size(); ++j)
                 {
+                    CAPTURE(i);
+                    CAPTURE(j);
                     // check definition
                     CHECK( (j_values[i] >= j_values[j]) == not(j_values[i] < j_values[j]) );
                 }
@@ -9009,6 +9661,23 @@ TEST_CASE("parser class")
                     // (2**53)-1
                     CHECK(json::parser("9007199254740991").parse().get<int64_t>() == 9007199254740991);
                 }
+                
+                SECTION("over the edge cases")  // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
+                {
+                    // While RFC7159, Section 6 specifies a preference for support
+                    // for ranges in range of IEEE 754-2008 binary64 (double precision)
+                    // this does not accommodate 64 bit integers without loss of accuracy.
+                    // As 64 bit integers are now widely used in software, it is desirable
+                    // to expand support to to the full 64 bit (signed and unsigned) range
+                    // i.e. -(2**63) -> (2**64)-1.
+
+                    // -(2**63)    ** Note: compilers see negative literals as negated positive numbers (hence the -1))
+                    CHECK(json::parser("-9223372036854775808").parse().get<int64_t>() == -9223372036854775807-1);
+                    // (2**63)-1
+                    CHECK(json::parser("9223372036854775807").parse().get<int64_t>() == 9223372036854775807);
+                    // (2**64)-1
+                    CHECK(json::parser("18446744073709551615").parse().get<uint64_t>() == 18446744073709551615u);
+                }
             }
 
             SECTION("floating-point")
@@ -9051,12 +9720,12 @@ TEST_CASE("parser class")
 
                 CHECK_THROWS_WITH(json::parser("01").parse(), "parse error - 0 is not a number");
                 CHECK_THROWS_WITH(json::parser("--1").parse(), "parse error - unexpected '-'");
-                CHECK_THROWS_WITH(json::parser("1.").parse(), "parse error - 1 is not a number");
+                CHECK_THROWS_WITH(json::parser("1.").parse(), "parse error - unexpected '.'; expected end of input");
                 CHECK_THROWS_WITH(json::parser("1E").parse(),
                                   "parse error - unexpected 'E'; expected end of input");
                 CHECK_THROWS_WITH(json::parser("1E-").parse(),
                                   "parse error - unexpected 'E'; expected end of input");
-                CHECK_THROWS_WITH(json::parser("1.E1").parse(), "parse error - 1 is not a number");
+                CHECK_THROWS_WITH(json::parser("1.E1").parse(), "parse error - unexpected '.'; expected end of input");
                 CHECK_THROWS_WITH(json::parser("-1E").parse(),
                                   "parse error - unexpected 'E'; expected end of input");
                 CHECK_THROWS_WITH(json::parser("-0E#").parse(),
@@ -9098,18 +9767,18 @@ TEST_CASE("parser class")
         CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument);
         CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument);
         CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument);
-        CHECK_THROWS_WITH(json::parser("0.").parse(), "parse error - 0 is not a number");
+        CHECK_THROWS_WITH(json::parser("0.").parse(), "parse error - unexpected '.'; expected end of input");
         CHECK_THROWS_WITH(json::parser("-").parse(), "parse error - unexpected '-'");
         CHECK_THROWS_WITH(json::parser("--").parse(),
                           "parse error - unexpected '-'");
         CHECK_THROWS_WITH(json::parser("-0.").parse(),
-                          "parse error - -0 is not a number");
+                          "parse error - unexpected '.'; expected end of input");
         CHECK_THROWS_WITH(json::parser("-.").parse(),
                           "parse error - unexpected '-'");
         CHECK_THROWS_WITH(json::parser("-:").parse(),
                           "parse error - unexpected '-'");
         CHECK_THROWS_WITH(json::parser("0.:").parse(),
-                          "parse error - 0 is not a number");
+                          "parse error - unexpected '.'; expected end of input");
         CHECK_THROWS_WITH(json::parser("e.").parse(),
                           "parse error - unexpected 'e'");
         CHECK_THROWS_WITH(json::parser("1e.").parse(),
@@ -11082,14 +11751,14 @@ TEST_CASE("compliance tests from nativejson-benchmark")
                     "test/json_roundtrip/roundtrip10.json",
                     "test/json_roundtrip/roundtrip11.json",
                     "test/json_roundtrip/roundtrip12.json",
-                    //"test/json_roundtrip/roundtrip13.json",
+                    "test/json_roundtrip/roundtrip13.json",
                     "test/json_roundtrip/roundtrip14.json",
                     "test/json_roundtrip/roundtrip15.json",
                     "test/json_roundtrip/roundtrip16.json",
                     "test/json_roundtrip/roundtrip17.json",
-                    //"test/json_roundtrip/roundtrip18.json",
-                    //"test/json_roundtrip/roundtrip19.json",
-                    //"test/json_roundtrip/roundtrip20.json",
+                    "test/json_roundtrip/roundtrip18.json",
+                    "test/json_roundtrip/roundtrip19.json",
+                    "test/json_roundtrip/roundtrip20.json",
                     "test/json_roundtrip/roundtrip21.json",
                     "test/json_roundtrip/roundtrip22.json",
                     "test/json_roundtrip/roundtrip23.json",
@@ -11407,11 +12076,33 @@ TEST_CASE("regression tests")
     SECTION("issue #89 - nonstandard integer type")
     {
         // create JSON class with nonstandard integer number type
-        using custom_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, float>;
+        using custom_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>;
         custom_json j;
         j["int_1"] = 1;
         // we need to cast to int to compile with Catch - the value is int32_t
         CHECK(static_cast<int>(j["int_1"]) == 1);
+
+        // tests for correct handling of non-standard integers that overflow the type selected by the user
+        
+        // unsigned integer object creation - expected to wrap and still be stored as an integer
+        j = 4294967296U; // 2^32
+        CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_unsigned));
+        CHECK(j.get<uint32_t>() == 0);  // Wrap
+
+        // unsigned integer parsing - expected to overflow and be stored as a float
+        j = custom_json::parse("4294967296"); // 2^32
+        CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
+        CHECK(j.get<float>() == 4294967296.0);
+
+        // integer object creation - expected to wrap and still be stored as an integer
+        j = -2147483649LL; // -2^31-1
+        CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_integer));
+        CHECK(j.get<int32_t>() == 2147483647.0);  // Wrap
+
+        // integer parsing - expected to overflow and be stored as a float
+        j = custom_json::parse("-2147483648"); // -2^31
+        CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
+        CHECK(j.get<float>() == -2147483648.0);
     }
 
     SECTION("issue #93 reverse_iterator operator inheritance problem")
@@ -11510,11 +12201,11 @@ TEST_CASE("regression tests")
     {
         CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
     }
-
+    
     SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
     {
         json j;
-
+        
         // Non-const access with key as "char []"
         char array_key[] = "Key1";
         CHECK_NOTHROW(j[array_key] = 1);
@@ -11549,7 +12240,7 @@ TEST_CASE("regression tests")
         // Const access with key as "const char[]"
         CHECK(j_const[const_array_key] == json(2));
 
-        //Const access with key as "char *"
+        // Const access with key as "char *"
         CHECK(j_const[ptr_key] == json(3));
 
         // Const access with key as "const char *"
@@ -11590,16 +12281,16 @@ TEST_CASE("regression tests")
         // create JSON class with nonstandard float number type
 
         // float
-        nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, float> j_float = 1.23e25f;
+        nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> j_float = 1.23e25f;
         CHECK(j_float.get<float>() == 1.23e25f);
 
         // double
-        nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, double> j_double = 1.23e45;
-        CHECK(j_double.get<double>() == 1.23e45);
+        nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> j_double = 1.23e35f;
+        CHECK(j_double.get<double>() == 1.23e35f);
 
         // long double
-        nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, long double> j_long_double =
-            1.23e45L;
+        nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double> j_long_double = 1.23e45L;
         CHECK(j_long_double.get<long double>() == 1.23e45L);
     }
 }
+