Skip to content

Drop nulls

drop_nulls

Drop-nulls strategy — remove empty values recursively.

DropNullsStrategy

Bases: SmeltStrategy

Recursively remove None, empty strings, empty lists, and empty dicts.

Source code in packages/axm-smelt/src/axm_smelt/strategies/drop_nulls.py
Python
class DropNullsStrategy(SmeltStrategy):
    """Recursively remove None, empty strings, empty lists, and empty dicts."""

    @property
    def name(self) -> str:
        return "drop_nulls"

    @property
    def category(self) -> str:
        return "structural"

    def apply(self, ctx: SmeltContext) -> SmeltContext:
        """Remove empty values from JSON data.

        Uses ``ctx.parsed`` when available to skip
        ``json.loads``. Propagates the cleaned object as
        ``parsed`` on the returned context.
        """
        parsed = ctx.parsed
        if parsed is not None:
            cleaned = _clean(parsed)
            result = json.dumps(cleaned, separators=(",", ":"), ensure_ascii=False)
            new_ctx = SmeltContext(text=result, format=ctx.format)
            new_ctx._parsed = cleaned
            return new_ctx

        text = ctx.text
        stripped = text.strip()
        if not stripped:
            return ctx

        if stripped[0] in ("{", "["):
            try:
                data = json.loads(stripped)
                cleaned = _clean(data)
                result = json.dumps(cleaned, separators=(",", ":"), ensure_ascii=False)
                new_ctx = SmeltContext(text=result, format=ctx.format)
                new_ctx._parsed = cleaned
                return new_ctx
            except (json.JSONDecodeError, ValueError):
                pass

        return ctx
apply(ctx)

Remove empty values from JSON data.

Uses ctx.parsed when available to skip json.loads. Propagates the cleaned object as parsed on the returned context.

Source code in packages/axm-smelt/src/axm_smelt/strategies/drop_nulls.py
Python
def apply(self, ctx: SmeltContext) -> SmeltContext:
    """Remove empty values from JSON data.

    Uses ``ctx.parsed`` when available to skip
    ``json.loads``. Propagates the cleaned object as
    ``parsed`` on the returned context.
    """
    parsed = ctx.parsed
    if parsed is not None:
        cleaned = _clean(parsed)
        result = json.dumps(cleaned, separators=(",", ":"), ensure_ascii=False)
        new_ctx = SmeltContext(text=result, format=ctx.format)
        new_ctx._parsed = cleaned
        return new_ctx

    text = ctx.text
    stripped = text.strip()
    if not stripped:
        return ctx

    if stripped[0] in ("{", "["):
        try:
            data = json.loads(stripped)
            cleaned = _clean(data)
            result = json.dumps(cleaned, separators=(",", ":"), ensure_ascii=False)
            new_ctx = SmeltContext(text=result, format=ctx.format)
            new_ctx._parsed = cleaned
            return new_ctx
        except (json.JSONDecodeError, ValueError):
            pass

    return ctx