diff --git a/paramtools/parameters.py b/paramtools/parameters.py
index a44fc7c..1d91538 100644
--- a/paramtools/parameters.py
+++ b/paramtools/parameters.py
@@ -369,10 +369,14 @@ class Parameters:
                 f"\nYou may be able to describe this parameter's values with additional "
                 f"labels\nand the 'label_to_extend' operator."
             )
-        elif not shape:
-            exp_full_shape = 1
-        else:
-            exp_full_shape = reduce(lambda x, y: x * y, shape)
+        elif not shape and number_dims == 0:
+            data_type = self._numpy_type(param)
+            value = value_items[0]["value"]
+            if data_type == object:
+                return value
+            else:
+                return data_type(value)
+        exp_full_shape = reduce(lambda x, y: x * y, shape)
         if len(value_items) != exp_full_shape:
             # maintains label value order over value objects.
             exp_grid = list(itertools.product(*value_order.values()))

Scalar values are set as zero dimension arrays
When `array_first` is `True`, scalar values are set to zero dimension NumPy arrays. For the most part, these values act like normal Python `int`s or `float`s, but they cause problems in edge cases. Further, this behavior may confusing for new users. I'll open a PR this week to fix this.
diff --git a/paramtools/tests/test_parameters.py b/paramtools/tests/test_parameters.py
index 4d91777..d001829 100644
--- a/paramtools/tests/test_parameters.py
+++ b/paramtools/tests/test_parameters.py
@@ -833,7 +833,7 @@ class TestArrayFirst:
             [datetime.date(2018, 1, 15)]
         ]
         assert af_params.int_dense_array_param.tolist() == [[[4, 5, 6]]]
-        assert af_params.str_choice_param.tolist() == "value0"
+        assert af_params.str_choice_param == "value0"
 
     def test_from_array(self, af_params):
         exp = [
@@ -894,6 +894,31 @@ class TestArrayFirst:
         with pytest.raises(ParamToolsError):
             params.adjust({"arr": [{"label1": 1, "value": [4, 5, 6]}]})
 
+    def test_array_first_with_zero_dim(self):
+        class ZeroDim(Parameters):
+            defaults = {
+                "myint": {
+                    "title": "my int",
+                    "description": "",
+                    "type": "int",
+                    "value": 2,
+                },
+                "mystring": {
+                    "title": "my string",
+                    "description": "",
+                    "type": "str",
+                    "value": "hello world",
+                },
+            }
+            array_first = True
+
+        params = ZeroDim()
+        assert params.myint == 2.0
+        assert isinstance(params.myint, np.int64)
+
+        assert params.mystring == "hello world"
+        assert isinstance(params.mystring, str)
+
 
 class TestCollisions:
     def test_collision_list(self):

environment.yml
pip install -e .
parse_log_pytest
environment.yml
pytest
pre-commit install
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
black==23.3.0
cfgv==3.3.1
click==8.1.8
colorama @ file:///home/conda/feedstock_root/build_artifacts/colorama_1666700638685/work
distlib==0.3.9
exceptiongroup @ file:///home/conda/feedstock_root/build_artifacts/exceptiongroup_1720869315914/work
filelock==3.12.2
flake8==5.0.4
identify==2.5.24
importlib-metadata==4.2.0
iniconfig @ file:///home/conda/feedstock_root/build_artifacts/iniconfig_1673103042956/work
marshmallow @ file:///home/conda/feedstock_root/build_artifacts/marshmallow_1704873359756/work
mccabe==0.7.0
mypy-extensions==1.0.0
nodeenv==1.9.1
numpy @ file:///home/conda/feedstock_root/build_artifacts/numpy_1649806299270/work
packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1696202382185/work
-e git+https://github.com/PSLmodels/ParamTools.git@06d113a25a3a6e3193fc3704c40a92cbcfdbe80b#egg=paramtools
pathspec==0.11.2
platformdirs==2.6.2
pluggy @ file:///home/conda/feedstock_root/build_artifacts/pluggy_1648772594554/work
pre-commit==2.21.0
pycodestyle==2.9.1
pyflakes==2.5.0
pytest @ file:///home/conda/feedstock_root/build_artifacts/pytest_1704035161844/work
python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1709299778482/work
PyYAML==6.0.1
six @ file:///home/conda/feedstock_root/build_artifacts/six_1620240208055/work
tomli @ file:///home/conda/feedstock_root/build_artifacts/tomli_1727974628237/work
typed-ast==1.5.5
typing_extensions @ file:///home/conda/feedstock_root/build_artifacts/typing_extensions_1688315532570/work
virtualenv==20.16.2
zipp @ file:///home/conda/feedstock_root/build_artifacts/zipp_1677313463193/work

name: ParamTools
channels:
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=conda_forge
  - _openmp_mutex=4.5=2_gnu
  - ca-certificates=2025.1.31=hbcca054_0
  - colorama=0.4.6=pyhd8ed1ab_0
  - exceptiongroup=1.2.2=pyhd8ed1ab_0
  - importlib_metadata=4.11.4=hd8ed1ab_0
  - iniconfig=2.0.0=pyhd8ed1ab_0
  - ld_impl_linux-64=2.43=h712a8e2_4
  - libblas=3.9.0=31_h59b9bed_openblas
  - libcblas=3.9.0=31_he106b2a_openblas
  - libffi=3.4.6=h2dba641_0
  - libgcc=14.2.0=h767d61c_2
  - libgcc-ng=14.2.0=h69a702a_2
  - libgfortran=14.2.0=h69a702a_2
  - libgfortran5=14.2.0=hf1ad2bd_2
  - libgomp=14.2.0=h767d61c_2
  - liblapack=3.9.0=31_h7ac8fdf_openblas
  - liblzma=5.6.4=hb9d3cd8_0
  - liblzma-devel=5.6.4=hb9d3cd8_0
  - libnsl=2.0.1=hd590300_0
  - libopenblas=0.3.29=pthreads_h94d23a6_0
  - libsqlite=3.49.1=hee588c1_2
  - libstdcxx=14.2.0=h8f9b012_2
  - libstdcxx-ng=14.2.0=h4852527_2
  - libzlib=1.3.1=hb9d3cd8_2
  - marshmallow=3.20.2=pyhd8ed1ab_0
  - ncurses=6.5=h2d0b736_3
  - numpy=1.21.6=py37h976b520_0
  - openssl=3.4.1=h7b32b05_0
  - packaging=23.2=pyhd8ed1ab_0
  - pip=24.0=pyhd8ed1ab_0
  - pluggy=1.0.0=py37h89c1867_3
  - pytest=7.4.4=pyhd8ed1ab_0
  - python=3.7.12=hf930737_100_cpython
  - python-dateutil=2.9.0=pyhd8ed1ab_0
  - python_abi=3.7=4_cp37m
  - readline=8.2=h8c095d6_2
  - setuptools=69.0.3=pyhd8ed1ab_0
  - six=1.16.0=pyh6c4a22f_0
  - sqlite=3.49.1=h9eae976_2
  - tk=8.6.13=noxft_h4845f30_101
  - tomli=2.0.2=pyhd8ed1ab_0
  - typing_extensions=4.7.1=pyha770c72_0
  - wheel=0.42.0=pyhd8ed1ab_0
  - xz=5.6.4=hbcc6ac9_0
  - xz-gpl-tools=5.6.4=hbcc6ac9_0
  - xz-tools=5.6.4=hb9d3cd8_0
  - zipp=3.15.0=pyhd8ed1ab_0
  - pip:
      - black==23.3.0
      - cfgv==3.3.1
      - click==8.1.8
      - distlib==0.3.9
      - filelock==3.12.2
      - flake8==5.0.4
      - identify==2.5.24
      - importlib-metadata==4.2.0
      - mccabe==0.7.0
      - mypy-extensions==1.0.0
      - nodeenv==1.9.1
      - paramtools==0.0.0
      - pathspec==0.11.2
      - platformdirs==2.6.2
      - pre-commit==2.21.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pyyaml==6.0.1
      - typed-ast==1.5.5
      - virtualenv==20.16.2
prefix: /opt/conda/envs/ParamTools

paramtools/tests/test_parameters.py::TestArrayFirst::test_array_first_with_zero_dim
paramtools/tests/test_parameters.py::test_init paramtools/tests/test_parameters.py::TestSchema::test_empty_schema paramtools/tests/test_parameters.py::TestSchema::test_schema_just_labels paramtools/tests/test_parameters.py::TestSchema::test_schema_just_additional_members paramtools/tests/test_parameters.py::TestSchema::test_schema_not_dropped paramtools/tests/test_parameters.py::TestSchema::test_schema_with_errors paramtools/tests/test_parameters.py::TestSchema::test_actions_spec paramtools/tests/test_parameters.py::TestAccess::test_specification paramtools/tests/test_parameters.py::TestAccess::test_is_ordered paramtools/tests/test_parameters.py::TestAccess::test_specification_query paramtools/tests/test_parameters.py::TestAccess::test_serializable paramtools/tests/test_parameters.py::TestAccess::test_dump paramtools/tests/test_parameters.py::TestAccess::test_dump_with_labels paramtools/tests/test_parameters.py::TestAccess::test_iterable paramtools/tests/test_parameters.py::TestAdjust::test_adjust_int_param paramtools/tests/test_parameters.py::TestAdjust::test_simultaneous_adjust paramtools/tests/test_parameters.py::TestAdjust::test_adjust_many_labels paramtools/tests/test_parameters.py::TestAdjust::test_adjust_none_basic paramtools/tests/test_parameters.py::TestAdjust::test_adjust_none_many_values paramtools/tests/test_parameters.py::TestErrors::test_errors_attribute paramtools/tests/test_parameters.py::TestErrors::test_errors paramtools/tests/test_parameters.py::TestErrors::test_errors_choice_param paramtools/tests/test_parameters.py::TestErrors::test_errors_default_reference_param paramtools/tests/test_parameters.py::TestErrors::test_errors_int_param paramtools/tests/test_parameters.py::TestErrors::test_errors_multiple_params paramtools/tests/test_parameters.py::TestErrors::test_list_type_errors paramtools/tests/test_parameters.py::TestErrors::test_range_validation_on_list_param paramtools/tests/test_parameters.py::TestArray::test_to_array paramtools/tests/test_parameters.py::TestArray::test_from_array paramtools/tests/test_parameters.py::TestArray::test_resolve_order paramtools/tests/test_parameters.py::TestArray::test_to_array_with_state1 paramtools/tests/test_parameters.py::TestArray::test_to_array_with_state2 paramtools/tests/test_parameters.py::TestState::test_basic_set_state paramtools/tests/test_parameters.py::TestState::test_label_grid paramtools/tests/test_parameters.py::TestState::test_set_state_updates_values paramtools/tests/test_parameters.py::TestState::test_set_state_errors paramtools/tests/test_parameters.py::TestState::test_state_with_list paramtools/tests/test_parameters.py::TestArrayFirst::test_basic paramtools/tests/test_parameters.py::TestArrayFirst::test_from_array paramtools/tests/test_parameters.py::TestArrayFirst::test_to_array_with_nd_lists paramtools/tests/test_parameters.py::TestCollisions::test_collision_list paramtools/tests/test_parameters.py::TestCollisions::test_collision paramtools/tests/test_parameters.py::TestExtend::test_extend_num paramtools/tests/test_parameters.py::TestExtend::test_extend_categorical paramtools/tests/test_parameters.py::TestExtend::test_extend_w_array paramtools/tests/test_parameters.py::TestExtend::test_extend_adj paramtools/tests/test_parameters.py::TestExtend::test_extend_adj_w_errors paramtools/tests/test_parameters.py::TestExtend::test_extend_adj_nonextend_param paramtools/tests/test_parameters.py::TestExtend::test_extend_adj_w_set_state paramtools/tests/test_parameters.py::TestExtend::test_custom_extend paramtools/tests/test_parameters.py::TestIndex::test_index_simple paramtools/tests/test_parameters.py::TestIndex::test_related_param_errors
paramtools/parameters.py
paramtools/parameters.py