liveBook · Manning

Parsing

As explained in Build Financial Software with Generative AI (From Scratch)

Parsing is the process of analyzing structured input and converting it into accessible data elements according to its format.

Parsing turns ACH record lines into accessible fields that application code can use. A parser separates each record type into its own routine, then reads fixed character ranges into named dictionary values such as priority code, institution identifiers, account number, and amount. This keeps record-specific layout rules visible rather than burying them in file-loading logic. section 2.4.2

Listing 2.5 Starting point for our ACH parser
def parse_file_header(line):
    return {
        'record_type': 'File Header',
        'priority_code': line[1:3],
        'immediate_destination': line[3:13],
        'immediate_origin': line[13:23],
        # ... additional fields
    }

def parse_batch_header(line):
    return {
        'record_type': 'Batch Header',
        'service_class_code': line[1:4],
        'company_name': line[4:20],
        # ... additional fields
    }

def parse_entry_detail(line):
    return {
        'record_type': 'Entry Detail',
        'transaction_code': line[1:3],
        'receiving_dfi_id': line[3:11],
        'account_number': line[12:29],
        'amount': line[29:39],
        # ... additional fields
    }

def parse_addenda(line):
    return {
        'record_type': 'Addenda',
        # ... additional fields based on the specific addenda type
    }

def parse_batch_control(line):
    return {
        'record_type': 'Batch Control',
        # ... additional fields
    }

def parse_file_control(line):
    return {
        'record_type': 'File Control',
        # ... additional fields
    }

def parse_ach(filename):
    records = []

    parser_functions = {
        '1': parse_file_header,
        '5': parse_batch_header,
        '6': parse_entry_detail,
        '7': parse_addenda,
        '8': parse_batch_control,
        '9': parse_file_control
    }

    with open(filename, 'r') as file:
        lines = file.readlines()

        for line in lines:
            record_type = line[0]
            parser = parser_functions.get(record_type)

            if parser:
                records.append(parser(line))
            else:
                print(f"Unknown record type: {record_type} in line: {line}")
                continue

    return records


# Test the function with an ACH file
parsed_records = parse_ach('path_to_ach_file.txt')
for record in parsed_records:
    print(record)

The starter routines show the core pattern: identify a record type, slice its fixed-width positions, and return a dictionary of named fields. Separate functions make file header, batch header, entry detail, and addenda layouts easier to extend and test independently. section 2.4.2

Start with a narrow parsing goal before adding broader processing behavior. Parsing alone does not guarantee safe input: defensive coding also calls for input validation, error handling, fail-safe defaults, output sanitization, logging or monitoring, and static analysis. Treat unexpected lengths, invalid record types, and unusual whitespace as inputs that need explicit decisions rather than assumptions. section 2.4.2 section 2.4.3

Verify a file header parser

Pass a sample type-1 file-header line to a parser and compare its returned dictionary with an expected result. The check can reveal layout mistakes, such as interpreting an eight-position creation date where the format expects six or accepting a record that is not 94 bytes long. A failing comparison makes the differing fields visible; tests can also assert that malformed records raise errors. section 2.4.3

Use small development cycles to make parsing changes safer:

  • Break record handling into functions so each record type can be checked independently. section 2.5.4
  • Write a unit test that fails for the required behavior, then implement only enough parsing logic to make it pass. section 2.5.4
  • Check generated code against sample records and expected output; generated assumptions about lengths and field positions can be wrong. section 2.4.3
  • Preserve existing batch behavior while integrating new record types, including the presence and order of addenda records. section 11.5

Parsing individual records is only one part of file processing. Once individual routines are verified, integrate them into the actual ACH-file loading flow and confirm that the resulting records are stored as expected. For IAT batches, that means ensuring the IAT batch-header routine is actually called while ordinary PPD batches continue to work and addenda remain complete and ordered. section 11.5

How Build Financial Software with Generative AI (From Scratch) covers it

How deep it goes
Works through fixed-width field extraction, unit tests, malformed inputs, and batch-flow integration rather than format specification details.
Examples
Uses file headers, batch headers, entry details, addenda, sample ACH files, expected dictionaries, and pytest assertions.
What it assumes
Introduces parsing through Python routines and pytest-style assertions without assuming prior finance or infrastructure expertise.
What you can do after
Build it from scratch by separating ACH record parsers, testing expected fields, and integrating verified routines into file loading.
How it connects
Connects parsing with ACH files, input validation, defensive coding, unit testing, pytest, generative AI, IAT, PPD, and addenda records.

Also explained in

Compare how 13 books explain parsing →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Build Financial Software with Generative AI (From Scratch). The section links point to the parts of the book it draws on.