Repository: voxel51/fiftyone
Issue: [BUG] 1D arrays are not serialized correctly

The `array1d` field here gets corrupted, but shouldn't

```py
import numpy as np

import fiftyone as fo

sample = fo.Sample(
    filepath="/path/to/image.png",
    list=[0, 1, 2, 3, 4],
    array1d=np.arange(5),
    array2d=np.random.randn(3, 3),
)
print(sample)

dataset = fo.Dataset()
dataset.add_sample(sample)
print(sample)
```

```
<Sample: {
    'id': None,
    'filepath': '/path/to/image.png',
    'tags': [],
    'metadata': None,
    'list': [0, 1, 2, 3, 4],
    'array1d': array([0, 1, 2, 3, 4]),
    'array2d': array([[-0.56765033,  0.56883355, -0.98888142],
           [ 0.08255658, -0.93718153, -0.96438669],
           [-0.26177874, -0.47903185, -0.63013481]]),
}>
```

```
<Sample: {
    'id': '5f6cb8563823835decef0b23',
    'filepath': '/path/to/image.png',
    'tags': BaseList([]),
    'metadata': None,
    'list': BaseList([0, 1, 2, 3, 4]),
    'array1d': array(b'x\\x9c\\x9b\\xec\\x17\\xea\\x1b\\x10\\xc9\\xc8P\\xc6P\\xad\\x9e\\x92Z\\x9c\\\\\\xa4n\\xa5\\xa0n\\x93i\\xa1\\xae\\xa3\\xa0\\x9e\\x96_TR\\x94\\x98\\x17\\x9f_\\x94\\x92\\n\\x12wK\\xcc)N\\x05\\x8a\\x17g$\\x16\\xa4\\x02\\xf9\\x1a\\xa6:\\x9a:\\n\\xb5\\n\\x14\\x00.\\x06(`\\x84\\xd2LP\\x9a\\x19J\\xb3@i\\x00\\x9e\\x94\\x1bm',
          dtype='|S87'),
    'array2d': array([[-0.56765033,  0.56883355, -0.98888142],
           [ 0.08255658, -0.93718153, -0.96438669],
           [-0.26177874, -0.47903185, -0.63013481]]),
}>
```


Changed files:
fiftyone/core/fields.py, fiftyone/core/odm/sample.py

diff --git a/fiftyone/core/fields.py b/fiftyone/core/fields.py
index 40e62485d..9a2720c00 100644
--- a/fiftyone/core/fields.py
+++ b/fiftyone/core/fields.py
@@ -162,31 +162,33 @@ class DictField(mongoengine.DictField, Field):
         return etau.get_class_name(self)
 
 
-class VectorField(Field):
+class VectorField(mongoengine.fields.BinaryField, Field):
     """A one-dimensional array field.
 
-    :class:`VectorField` instances accept lists, tuples, and numpy array
-    values. The underlying data is stored as a list in the database and always
-    retrieved as a numpy array.
+    :class:`VectorField` instances accept numeric lists, tuples, and 1D numpy
+    array values. The underlying data is serialized and stored in the database
+    as zlib-compressed bytes generated by ``numpy.save`` and always retrieved
+    as a numpy array.
     """
 
     def to_mongo(self, value):
         if value is None:
             return None
 
-        return np.asarray(value).tolist()
+        bytes = fou.serialize_numpy_array(value)
+        return super().to_mongo(bytes)
 
     def to_python(self, value):
         if value is None or isinstance(value, np.ndarray):
             return value
 
-        return np.asarray(value)
+        return fou.deserialize_numpy_array(value)
 
     def validate(self, value):
         if isinstance(value, np.ndarray):
             if value.ndim > 1:
                 self.error("Only 1D arrays may be used in a vector field")
-        elif not isinstance(value, (list, tuple)):
+        elif not isinstance(value, (list, tuple, Binary)):
             self.error(
                 "Only numpy arrays, lists, and tuples may be used in a "
                 "vector field"
diff --git a/fiftyone/core/odm/sample.py b/fiftyone/core/odm/sample.py
index 786286e82..80556ff8f 100644
--- a/fiftyone/core/odm/sample.py
+++ b/fiftyone/core/odm/sample.py
@@ -784,15 +784,6 @@ class NoDatasetSampleDocument(SampleDocument):
                 d[k] = v.to_dict(extended=extended)
             elif isinstance(v, np.ndarray):
                 # Must handle arrays separately, since they are non-primitives
-
-                # @todo cannot support serializing 1D arrays as lists because
-                # there is no way for `from_dict` to know that the data should
-                # be converted back to a numpy array
-                #
-                # if v.ndim == 1:
-                #     d[k] = v.tolist()
-                #
-
                 v_binary = fou.serialize_numpy_array(v)
                 if extended:
                     # @todo improve this