diff --git a/pynamodb/models.py b/pynamodb/models.py
index cacb817..19ca4f9 100644
--- a/pynamodb/models.py
+++ b/pynamodb/models.py
@@ -894,6 +894,9 @@ class Model(AttributeContainer):
         Reconstructs a model object from JSON.
         """
         hash_key, attrs = data
+        hash_keyname = cls._get_meta_data().hash_keyname
+        hash_key_attr = cls._get_attributes().get(cls._dynamo_to_python_attr(hash_keyname))
+        hash_key = hash_key_attr.deserialize(hash_key)
         range_key = attrs.pop('range_key', None)
         attributes = attrs.pop(pythonic(ATTRIBUTES))
         if range_key is not None:

Deserialize hash key while loading from json
While trying to load a table from a json dump, https://github.com/jlafon/PynamoDB/blob/devel/pynamodb/models.py#L764 does not deserialize the hash key. Hence, we run into an exception if the hash key is anything other than a UnicodeAttribute. 

For example, the following will lead to an exception.

```
from pynamodb.models import Model
from pynamodb.attributes import (
    UnicodeAttribute, NumberAttribute
)

class Thread(Model):
    class Meta:
        table_name = 'Thread'

    forum_name = NumberAttribute(hash_key=True)
    subject = UnicodeAttribute(range_key=True)
    views = NumberAttribute(default=0)

# After the table has been populated

Thread.dump("thread_backup.json")
Thread.load("thread_backup.json")
```

diff --git a/pynamodb/tests/data.py b/pynamodb/tests/data.py
index 3a76e22..5f624cd 100644
--- a/pynamodb/tests/data.py
+++ b/pynamodb/tests/data.py
@@ -466,7 +466,7 @@ COMPLEX_MODEL_ITEM_DATA = {
                     'N': '31'
                 },
                 'is_dude': {
-                    'N': '1'
+                    'BOOL': True
                 }
             }
         }
@@ -826,6 +826,33 @@ SERIALIZED_TABLE_DATA = [
     ]
 ]
 
+COMPLEX_MODEL_SERIALIZED_TABLE_DATA = [
+    [
+        "123",
+        {
+            "attributes": {
+                'person': {  # TODO(jpinner) fix deserialize lookup to use attr_name
+                    'M': {
+                        'firstName': {
+                            'S': 'Justin'
+                        },
+                        'lname': {
+                            'S': 'Phillips'
+                        },
+                        'age': {
+                            'N': '31'
+                        },
+                        'is_dude': {
+                            'N': '1'
+                        }
+                    }
+
+                }
+            }
+        }
+    ]
+]
+
 OFFICE_EMPLOYEE_MODEL_TABLE_DATA = {
     "Table": {
         "AttributeDefinitions": [
diff --git a/pynamodb/tests/test_model.py b/pynamodb/tests/test_model.py
index 9870dbd..0f15b96 100644
--- a/pynamodb/tests/test_model.py
+++ b/pynamodb/tests/test_model.py
@@ -36,7 +36,7 @@ from pynamodb.tests.data import (
     BATCH_GET_ITEMS, SIMPLE_BATCH_GET_ITEMS, COMPLEX_TABLE_DATA,
     COMPLEX_ITEM_DATA, INDEX_TABLE_DATA, LOCAL_INDEX_TABLE_DATA, DOG_TABLE_DATA,
     CUSTOM_ATTR_NAME_INDEX_TABLE_DATA, CUSTOM_ATTR_NAME_ITEM_DATA,
-    BINARY_ATTR_DATA, SERIALIZED_TABLE_DATA, OFFICE_EMPLOYEE_MODEL_TABLE_DATA,
+    BINARY_ATTR_DATA, SERIALIZED_TABLE_DATA, OFFICE_EMPLOYEE_MODEL_TABLE_DATA, COMPLEX_MODEL_SERIALIZED_TABLE_DATA,
     GET_OFFICE_EMPLOYEE_ITEM_DATA, GET_OFFICE_EMPLOYEE_ITEM_DATA_WITH_NULL,
     GROCERY_LIST_MODEL_TABLE_DATA, GET_GROCERY_LIST_ITEM_DATA,
     GET_OFFICE_ITEM_DATA, OFFICE_MODEL_TABLE_DATA, COMPLEX_MODEL_TABLE_DATA, COMPLEX_MODEL_ITEM_DATA,
@@ -3732,6 +3732,20 @@ class ModelTestCase(TestCase):
         }
         self.assert_dict_lists_equal(req.call_args[0][1]['RequestItems']['UserModel'], args['UserModel'])
 
+    def test_loads_complex_model(self):
+        with patch(PATCH_METHOD) as req:
+            req.return_value = {}
+            ComplexModel.loads(json.dumps(COMPLEX_MODEL_SERIALIZED_TABLE_DATA))
+
+        args = {
+            'ComplexModel': [
+                {
+                    'PutRequest': COMPLEX_MODEL_ITEM_DATA
+                }
+            ]
+        }
+        self.assert_dict_lists_equal(req.call_args[0][1]['RequestItems']['ComplexModel'], args['ComplexModel'])
+
     def _get_office_employee(self):
         justin = Person(
             fname='Justin',

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-mock pytest
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
botocore==1.2.0
certifi==2021.5.30
coverage==6.2
docutils==0.18.1
importlib-metadata==4.8.3
iniconfig==1.1.1
jmespath==0.7.1
packaging==21.3
pluggy==1.0.0
py==1.11.0
-e git+https://github.com/pynamodb/PynamoDB.git@7a3cc8aba43b4cfe7630f5a4a199bddb8f8c7a86#egg=pynamodb
pyparsing==3.1.4
pytest==7.0.1
pytest-cov==4.0.0
pytest-mock==3.6.1
python-dateutil==2.9.0.post0
six==1.9.0
tomli==1.2.3
typing_extensions==4.1.1
zipp==3.6.0

name: PynamoDB
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - botocore==1.2.0
      - coverage==6.2
      - docutils==0.18.1
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - jmespath==0.7.1
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-cov==4.0.0
      - pytest-mock==3.6.1
      - python-dateutil==2.9.0.post0
      - six==1.9.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/PynamoDB

pynamodb/tests/test_model.py::ModelTestCase::test_loads_complex_model
pynamodb/tests/test_model.py::ModelTestCase::test_batch_get pynamodb/tests/test_model.py::ModelTestCase::test_batch_write pynamodb/tests/test_model.py::ModelTestCase::test_batch_write_with_unprocessed pynamodb/tests/test_model.py::ModelTestCase::test_car_model_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_car_model_with_null_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_complex_key pynamodb/tests/test_model.py::ModelTestCase::test_complex_model_is_complex pynamodb/tests/test_model.py::ModelTestCase::test_complex_model_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_conditional_operator_map_attribute pynamodb/tests/test_model.py::ModelTestCase::test_count pynamodb/tests/test_model.py::ModelTestCase::test_count_no_hash_key pynamodb/tests/test_model.py::ModelTestCase::test_create_model pynamodb/tests/test_model.py::ModelTestCase::test_delete pynamodb/tests/test_model.py::ModelTestCase::test_delete_doesnt_do_validation_on_null_attributes pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_map_four_layers_deep_works pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_new_style_bool_false_works pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_new_style_bool_true_works pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_old_style_bool_false_works pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_old_style_bool_true_works pynamodb/tests/test_model.py::ModelTestCase::test_dumps pynamodb/tests/test_model.py::ModelTestCase::test_explicit_raw_map_serialize_pass pynamodb/tests/test_model.py::ModelTestCase::test_filter_count pynamodb/tests/test_model.py::ModelTestCase::test_get pynamodb/tests/test_model.py::ModelTestCase::test_global_index pynamodb/tests/test_model.py::ModelTestCase::test_index_count pynamodb/tests/test_model.py::ModelTestCase::test_index_multipage_count pynamodb/tests/test_model.py::ModelTestCase::test_index_queries pynamodb/tests/test_model.py::ModelTestCase::test_invalid_car_model_with_null_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_invalid_map_model_raises pynamodb/tests/test_model.py::ModelTestCase::test_list_of_map_works_like_list_of_map pynamodb/tests/test_model.py::ModelTestCase::test_list_works_like_list pynamodb/tests/test_model.py::ModelTestCase::test_loads pynamodb/tests/test_model.py::ModelTestCase::test_local_index pynamodb/tests/test_model.py::ModelTestCase::test_model_attrs pynamodb/tests/test_model.py::ModelTestCase::test_model_subclass_attributes_inherited_on_create pynamodb/tests/test_model.py::ModelTestCase::test_model_with_invalid_data_does_not_validate pynamodb/tests/test_model.py::ModelTestCase::test_model_with_list pynamodb/tests/test_model.py::ModelTestCase::test_model_with_list_of_map pynamodb/tests/test_model.py::ModelTestCase::test_model_with_list_of_map_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_model_with_list_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_model_with_maps pynamodb/tests/test_model.py::ModelTestCase::test_model_with_maps_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_model_with_maps_with_nulls_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_model_with_maps_with_pythonic_attributes pynamodb/tests/test_model.py::ModelTestCase::test_model_with_nulls_validates pynamodb/tests/test_model.py::ModelTestCase::test_model_works_like_model pynamodb/tests/test_model.py::ModelTestCase::test_multiple_indices_share_non_key_attribute pynamodb/tests/test_model.py::ModelTestCase::test_new_style_boolean_serializes_as_bool pynamodb/tests/test_model.py::ModelTestCase::test_old_style_boolean_serializes_as_bool pynamodb/tests/test_model.py::ModelTestCase::test_old_style_model_exception pynamodb/tests/test_model.py::ModelTestCase::test_overidden_defaults pynamodb/tests/test_model.py::ModelTestCase::test_overidden_session pynamodb/tests/test_model.py::ModelTestCase::test_overridden_attr_name pynamodb/tests/test_model.py::ModelTestCase::test_projections pynamodb/tests/test_model.py::ModelTestCase::test_query pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_greater_than_available_items_and_page_size pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_greater_than_available_items_multiple_page pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_greater_than_available_items_single_page pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_identical_to_available_items_single_page pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_less_than_available_and_page_size pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_less_than_available_items_multiple_page pynamodb/tests/test_model.py::ModelTestCase::test_rate_limited_scan pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_as_sub_map pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_as_sub_map_deserialize pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_as_sub_map_from_raw_data_works pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_as_sub_map_serialize_pass pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_deserializes pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_from_raw_data_works pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_serialize_fun_one pynamodb/tests/test_model.py::ModelTestCase::test_refresh pynamodb/tests/test_model.py::ModelTestCase::test_result_set_init pynamodb/tests/test_model.py::ModelTestCase::test_result_set_iter pynamodb/tests/test_model.py::ModelTestCase::test_save pynamodb/tests/test_model.py::ModelTestCase::test_scan pynamodb/tests/test_model.py::ModelTestCase::test_scan_limit pynamodb/tests/test_model.py::ModelTestCase::test_scan_limit_with_page_size pynamodb/tests/test_model.py::ModelTestCase::test_update pynamodb/tests/test_model.py::ModelTestCase::test_update_item pynamodb/tests/test_model.py::ModelInitTestCase::test_raw_map_attribute_with_dict_init pynamodb/tests/test_model.py::ModelInitTestCase::test_raw_map_attribute_with_initialized_instance_init pynamodb/tests/test_model.py::ModelInitTestCase::test_subclassed_map_attribute_with_dict_init pynamodb/tests/test_model.py::ModelInitTestCase::test_subclassed_map_attribute_with_initialized_instance_init pynamodb/tests/test_model.py::ModelInitTestCase::test_subclassed_map_attribute_with_map_attribute_member_with_initialized_instance_init pynamodb/tests/test_model.py::ModelInitTestCase::test_subclassed_map_attribute_with_map_attributes_member_with_dict_init
pynamodb/models.py
pynamodb/models.py