OpenViSTAI · Agents · Blockchain · Crypto
Menu
OPENVIST RECIPES

Summarize field presence and value types in JSON records with Python

Python

Inspect a small JSON array of objects and report field coverage and top-level value type counts without printing the values.

Python code excerpt: Summarize field presence and value types in JSON records with Python. Version 0.1.0. Read the full recipe for code, sources and recorded test scope.

Inspect a small array of JSON objects from standard input. Count how often each field appears and which immediate value types occur. This reports observations, not an inferred schema. Input values are not printed; field names are included.

Before you start

  • Run with Python 3.12 as python3.12 summarize.py, supplying JSON through standard input. No command-line arguments are accepted.
  • Uses only the standard-library modules json, math, and sys. The program performs no filesystem operations.
  • Reads at most 65537 bytes from sys.stdin.buffer and rejects input exceeding 65536 bytes. UTF-8 decoding is strict.
  • Requires a JSON array containing only objects; an empty array is valid. Rejects malformed JSON, duplicate keys at every depth, nonstandard numeric constants, and float tokens that convert to infinity.
  • Successful input produces exactly one JSON object on stdout, exits 0, and produces no stderr. Fields are sorted by Python string ordering; type counts cover only immediate field values and omit zero counts.
  • Invalid input exits 2 with a fixed error message on stderr and no stdout. Diagnostics do not disclose input values or produce a traceback.

Build and check

  1. Save the example as summarize.py.
  2. Prepare a UTF-8 JSON array of objects, at most 65536 bytes.
  3. Run: python3 summarize.py < records.json
  4. Inspect records and the sorted fields array. Present counts records containing the field; missing is the remaining record count.
  5. Handle exit code 2 as invalid or unreadable input.

Limits to understand

  • Reports observed field presence and value types, not an inferred schema or a guarantee about future data.
  • Nested values are parsed and validated, but their internal fields and types are not summarized.
  • Input values are not printed; field names are included as required.
  • Integer tokens use an internal integer placeholder because only their type matters. This avoids Python's integer-conversion digit limit without changing the report.
  • Excessive nesting or resource exhaustion is rejected with a generic error. Floating-point conversion follows Python semantics, including finite rounding and underflow.
  • The entire input and parsed values are held in memory. Memory use can exceed the input byte size.
  • Standard input may block while waiting for data or EOF. The byte limit is not a timeout.
  • Output write failures are outside the input-validation error guarantee.
  • Field names can themselves contain sensitive information; inspect the report before sharing it.

Run it

python3 summarize.py < records.json

Example input

[{"name":"Ana","active":true},{"name":"José","age":30}]

Expected output

{"records":2,"fields":[{"name":"active","present":1,"missing":1,"types":{"boolean":1}},{"name":"age","present":1,"missing":1,"types":{"number":1}},{"name":"name","present":2,"missing":0,"types":{"string":2}}]}
INSPECT THE SCRIPT

Inspect, copy and run the documented checks.

This browser preview builds code locally. It does not contact an API or run the code.

Default example ready.

Python example
import json
import math
import sys


MAX_BYTES = 65536


def reject_constant(_token):
    raise ValueError('Nonstandard numeric constant')


def parse_integer(_token):
    # Only the numeric type matters; avoid Python's integer digit limit.
    return 0


def parse_float(token):
    value = float(token)
    if not math.isfinite(value):
        raise ValueError('Nonfinite number')
    return value


def unique_object(pairs):
    result = {}
    for key, value in pairs:
        if key in result:
            raise ValueError('Duplicate object key')
        result[key] = value
    return result


def value_type(value):
    if value is None:
        return 'null'
    if isinstance(value, bool):
        return 'boolean'
    if isinstance(value, (int, float)):
        return 'number'
    if isinstance(value, str):
        return 'string'
    if isinstance(value, list):
        return 'array'
    return 'object'


def main():
    if len(sys.argv) != 1:
        sys.stderr.write('error: no command-line arguments are accepted\n')
        return 2

    try:
        raw = sys.stdin.buffer.read(MAX_BYTES + 1)
        if len(raw) > MAX_BYTES:
            raise ValueError('Input too large')
        text = raw.decode('utf-8', errors='strict')
        records = json.loads(
            text,
            object_pairs_hook=unique_object,
            parse_int=parse_integer,
            parse_float=parse_float,
            parse_constant=reject_constant,
        )
        if not isinstance(records, list):
            raise ValueError('Expected an array')
        if any(not isinstance(record, dict) for record in records):
            raise ValueError('Expected objects in the array')

        counts = {}
        for record in records:
            for name, value in record.items():
                types = counts.setdefault(name, {})
                label = value_type(value)
                types[label] = types.get(label, 0) + 1

        total = len(records)
        labels = ('null', 'boolean', 'number', 'string', 'array', 'object')
        fields = []
        for name in sorted(counts):
            types = counts[name]
            present = sum(types.values())
            fields.append({
                'name': name,
                'present': present,
                'missing': total - present,
                'types': {label: types[label] for label in labels if label in types},
            })
        output = json.dumps(
            {'records': total, 'fields': fields},
            ensure_ascii=True,
            allow_nan=False,
            separators=(',', ':'),
        )
    except (ValueError, RecursionError, OverflowError, MemoryError, OSError):
        sys.stderr.write(
            'error: invalid, oversized, excessively nested, or unreadable input\n'
        )
        return 2

    sys.stdout.write(output + '\n')
    return 0


if __name__ == '__main__':
    sys.exit(main())
What to verify after running
  • Six independent CLI fixtures passed in offline CPython 3.12.15 Docker.
  • Checked mixed types, empty collections, missing and Unicode fields, container types, non-object records and duplicate keys.
  • Seven additional unittest methods passed in the same pinned Python image, including byte boundaries, invalid UTF-8, non-finite numbers, nested duplicate keys, invalid structure, extra arguments and a long integer.

Request or format preview

Illustrative preview. No provider response, price or balance is fetched.

Change a setting to inspect the preview.

Official sources and related profiles

    Code license: MIT. Keep the license notice with your copy.

    Example version 0.1.0 · Documentation reviewed 2026-10-14.

    Six independent CLI fixtures and seven additional boundary-test methods passed in pinned, offline CPython 3.12.15 Docker. These checks do not establish exhaustive correctness, performance for arbitrary inputs, or behavior on other Python versions.

    Related browser tools

    Inspect related data locally in your browser. These tools have their own input rules and limits; they do not execute this recipe.