Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ This project adheres to [Semantic Versioning].

## [Unreleased]

## [0.0.41] - 2026-05-18

### Fixed in 0.0.41

- `sz_explorer`: mappable attributes with null/empty values no longer appear in Additional Data (#391)

## [0.0.40] - 2026-04-23

### Fixed in 0.0.40
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "sz-python-tools"
version = "0.0.40"
version = "0.0.41"
description = "Senzing Python Tools"
authors = [{ name = "senzing", email = "support@senzing.com" }]
readme = "README.md"
Expand Down
46 changes: 46 additions & 0 deletions sz_tools/sz_explorer
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,50 @@ class EdaReports:
)


def _strip_null_values(value):
"""Recursively drop None and empty-string entries from nested dicts/lists.

Keeps 0, False, and other non-null values. Returns None if the container
collapses to empty so callers can drop it from a parent.
"""
if isinstance(value, dict):
cleaned = {}
for k, v in value.items():
if v is None or v == "":
continue
cv = _strip_null_values(v)
if cv is None:
continue
cleaned[k] = cv
return cleaned or None
if isinstance(value, list):
cleaned = []
for item in value:
if item is None or item == "":
continue
ci = _strip_null_values(item)
if ci is None:
continue
cleaned.append(ci)
return cleaned or None
return value


def _clean_unmapped_data(node):
"""Walk a parsed engine response and strip null/empty entries from every
UNMAPPED_DATA dict found anywhere in the structure. Mutates in place.
"""
if isinstance(node, dict):
if "UNMAPPED_DATA" in node:
cleaned = _strip_null_values(node["UNMAPPED_DATA"])
node["UNMAPPED_DATA"] = cleaned if cleaned else {}
for v in node.values():
_clean_unmapped_data(v)
elif isinstance(node, list):
for item in node:
_clean_unmapped_data(item)


class EdaSdkWrapper:

def __init__(self, engine_config, **kwargs):
Expand Down Expand Up @@ -1693,6 +1737,8 @@ class EdaSdkWrapper:
except SzError as err:
raise SzError(f"{api_name}: {err}") from None

_clean_unmapped_data(response_data)

if self.mask_pii:
mask_json_pii(response_data, self.mask_pii)

Expand Down
Loading