parser needs the map and array start even if there are no contents
MODIFY
fastavro/_write_py.py
fastavro/_write_py.py
@@ -98,9 +98,9 @@ def write_array(encoder, datum, schema):
If a block's count is negative, then the count is followed immediately by a
long block size, indicating the number of bytes in the block. The actual
count in this case is the absolute value of the count written. """
-
+ encoder.write_array_start()
if len(datum) > 0:
- encoder.write_array_start(len(datum))
+ encoder.write_item_count(len(datum))
dtype = schema['items']
for item in datum:
write_data(encoder, item, dtype)
@@ -118,8 +118,9 @@ def write_map(encoder, datum, schema):
If a block's count is negative, then the count is followed immediately by a
long block size, indicating the number of bytes in the block. The actual
count in this case is the absolute value of the count written."""
+ encoder.write_map_start()
if len(datum) > 0:
- encoder.write_map_start(len(datum))
+ encoder.write_item_count(len(datum))
vtype = schema['values']
for key, val in iteritems(datum):
encoder.write_utf8(key)

MODIFY
fastavro/io/binary_encoder.py
fastavro/io/binary_encoder.py
@@ -60,7 +60,10 @@ class BinaryEncoder:
def write_enum(self, index):
self.write_int(index)
- def write_array_start(self, length):
+ def write_array_start(self):
+ pass
+
+ def write_item_count(self, length):
self.write_long(length)
def end_item(self):
@@ -69,8 +72,8 @@ class BinaryEncoder:
def write_array_end(self):
self.write_long(0)
- def write_map_start(self, length):
- self.write_long(length)
+ def write_map_start(self):
+ pass
def write_map_end(self):
self.write_long(0)

MODIFY
fastavro/io/json_encoder.py
fastavro/io/json_encoder.py
@@ -132,11 +132,14 @@ class AvroJSONEncoder(object):
self._parser.advance(Fixed())
self.write_value(btou(value, encoding='iso-8859-1'))
- def write_array_start(self, length):
+ def write_array_start(self):
self._parser.advance(ArrayStart())
self._push()
self._current = []
+ def write_item_count(self, length):
+ pass
+
def end_item(self):
self._parser.advance(ItemEnd())
@@ -154,7 +157,7 @@ class AvroJSONEncoder(object):
def write_object_end(self):
self._pop()
- def write_map_start(self, length):
+ def write_map_start(self):
self._parser.advance(MapStart())
self.write_object_start()

MODIFY
tests/test_json.py
tests/test_json.py
@@ -312,3 +312,35 @@ def test_array_type_records():
new_records = roundtrip(schema, records)
assert records == new_records
+
+
+def test_empty_maps():
+ """https://github.com/fastavro/fastavro/issues/380"""
+ schema = {
+ "type": "map",
+ "values": "int",
+ }
+
+ records = [
+ {"foo": 1},
+ {},
+ ]
+
+ new_records = roundtrip(schema, records)
+ assert records == new_records
+
+
+def test_empty_arrays():
+ """https://github.com/fastavro/fastavro/issues/380"""
+ schema = {
+ "type": "array",
+ "items": "int",
+ }
+
+ records = [
+ [1],
+ [],
+ ]
+
+ new_records = roundtrip(schema, records)
+ assert records == new_records

parser needs the map and array start even if there are no contents