def merge_schemas(parent, child):
    """ Merge two json schemas.  Note that this method is asymmetric;
        if the child redefines a field present in the parent, the child's
        definition takes precedence.  But if either of them provide
        fields in the `requires` directive, those will be merged.

        :param parent: the parent operator's json schema
        :type parent: dict
        :param child: the child operator's json schema
        :type child: dict
        :returns: a new jsonschema reflecting the merger
        :rtype: dict
    """
    result = {'properties': {}}
    result['properties'].update(parent.get('properties', {}))
    result['properties'].update(child.get('properties', {}))
    required = parent.get('required', []) + child.get('required', [])
    if required:
        result['required'] = required
    for schema in [parent, child]:
        if 'additionalProperties' in schema:
            result['additionalProperties'] = schema['additionalProperties']
    extra_keys = (frozenset(parent) | frozenset(child)) - frozenset([
        'properties', 'required', 'additionalProperties'])
    if extra_keys:
        raise Exception(
            'Cannot merge schemas due to unrecognized fields: {} (parent schema: {}; child schema: {})'
            .format(extra_keys, parent, child))
    return result
