Roadmap / Retrieval & Information Extraction

✓

Validated JSON Extraction

mediuminformation-extractionstructured-output

The problem

A program often needs structured data from text: the fields of an invoice, the date in an email. A language model can be asked to read the text and answer in JSON (JavaScript Object Notation, a text format for structured data). But its output is not always clean: it may wrap the JSON in a markdown fence, or add a sentence before it ("Sure! Here it is:"), or return a field of the wrong type. So the pipeline has two parts: a tolerant parser that finds the JSON, and a strict validator that checks it against a schema.

Part 1: finding the JSON object

parse_json_object(text) returns the first JSON object in text as a dict, or None if there is none. Scan for each {, and try json.JSONDecoder().raw_decode(text, i) from there (it decodes one JSON value starting at position i and ignores what comes after); return the first result that decodes to a dict.

Example. The text is Sure! Here it is:, a newline, a markdown fence, and {"vendor": "ACME", "total": 42, "paid": true}. The first { starts a valid object: the result is {"vendor": "ACME", "total": 42, "paid": True}. A text with no valid object, such as no json, gives None.

Part 2: validation

The schema maps field names to (type, required), where the type is one of str, int, float, bool, list. validate(obj, schema) returns a list of error strings, empty if valid:

  • "missing: <field>" for a required field that is absent;
  • "type: <field>" for a present field of the wrong type. A float field also accepts an int, but no field accepts a bool unless its type is bool (in Python True is an int);
  • "extra: <field>" for any field not in the schema.

Report errors in schema order, then extras in the object's order.

Example. schema = {"vendor": (str, True), "total": (float, True), "date": (str, False)}.

  • {"vendor": "ACME", "total": 42, "paid": true}: ["extra: paid"]. The 42 is accepted as a float; the optional date is absent, which is fine.
  • {"total": "42"}: ["missing: vendor", "type: total"]: the total is text, not a number.

Part 3: both together

extract(text, schema) returns (obj, errors). If no object can be parsed: (None, ["no json object"]).

What to implement

  • parse_json_object(text), validate(obj, schema) and extract(text, schema) as described.

Requirements

  • Standard library only (json).
solution.py
Python idle

Press Run (⌘/Ctrl + Enter) to test your code.