union schema validation should still ignore extra fields
MODIFY
fastavro/_validation.pyx
fastavro/_validation.pyx
@@ -19,6 +19,9 @@ cdef int32 INT_MAX_VALUE = const.INT_MAX_VALUE
cdef long64 LONG_MIN_VALUE = const.LONG_MIN_VALUE
cdef long64 LONG_MAX_VALUE = const.LONG_MAX_VALUE
+no_value = object()
+
+
cdef inline bint validate_null(datum, schema=None,
str parent_ns='', bint raise_errors=True):
return datum is None
@@ -112,15 +115,11 @@ cdef inline bint validate_record(object datum, dict schema, str parent_ns='',
return False
_, namespace = schema_name(schema, parent_ns)
for f in schema['fields']:
- if not validate(datum=datum.get(f['name'], f.get('default')),
+ if not validate(datum=datum.get(f['name'], f.get('default', no_value)),
schema=f['type'],
field='{}.{}'.format(namespace, f['name']),
raise_errors=raise_errors):
return False
- field_names = [field['name'] for field in schema['fields']]
- for datum_field in iterkeys(datum):
- if datum_field not in field_names:
- return False
return True

MODIFY
fastavro/_validation_py.py
fastavro/_validation_py.py
@@ -11,6 +11,8 @@ from .schema import extract_record_type, UnknownType, schema_name
from .six import long, is_str, iterkeys, itervalues
from ._schema_common import SCHEMA_DEFS
+no_value = object()
+
def validate_null(datum, **kwargs):
"""
@@ -245,16 +247,14 @@ def validate_record(datum, schema, parent_ns=None, raise_errors=True):
If true, raises ValidationError on invalid data
"""
_, namespace = schema_name(schema, parent_ns)
- field_names = [field['name'] for field in schema['fields']]
return (
isinstance(datum, Mapping) and
- all(validate(datum=datum.get(f['name'], f.get('default')),
+ all(validate(datum=datum.get(f['name'], f.get('default', no_value)),
schema=f['type'],
field='{}.{}'.format(namespace, f['name']),
raise_errors=raise_errors)
for f in schema['fields']
- ) and
- all(datum_field in field_names for datum_field in iterkeys(datum))
+ )
)

MODIFY
tests/test_fastavro.py
tests/test_fastavro.py
@@ -1570,7 +1570,7 @@ def test_embedded_records_get_namespaced_correctly():
assert records == roundtrip(schema, records)
-def test_union_schema_checks_field_names():
+def test_null_defaults_are_not_used():
"""https://github.com/fastavro/fastavro/issues/272"""
schema = [{
"type": "record",
@@ -1589,3 +1589,20 @@ def test_union_schema_checks_field_names():
datum_to_read = {'entity': {'foo': 'this is an instance of schema A'}}
assert [datum_to_read] == roundtrip(schema, [datum_to_read])
+
+
+def test_union_schema_ignores_extra_fields():
+ """https://github.com/fastavro/fastavro/issues/274"""
+ schema = [{
+ "type": "record",
+ "name": "A",
+ "fields": [{"name": "name", "type": "string"}]
+ }, {
+ "type": "record",
+ "name": "B",
+ "fields": [{"name": "other_name", "type": "string"}]
+ }]
+
+ records = [{"name": "abc", "other": "asd"}]
+
+ assert [{"name": "abc"}] == roundtrip(schema, records)

union schema validation should still ignore extra fields