Mainframe Path Start learning free
Applied9 min readLesson 2 of 5

From copybook to JSON

Mainframe programs exchange fixed-layout records described by copybooks; APIs exchange JSON with named fields. Exposing a program as an API means mapping one onto the other, and most bugs live in that mapping.

The same data, two shapes

Copybook ACCTREC
01  ACCT-REC.
    05  ACCT-ID         PIC X(8).
    05  ACCT-NAME       PIC X(30).
    05  ACCT-BALANCE    PIC S9(9)V99 COMP-3.
    05  ACCT-STATUS     PIC X.
    05  TXN-COUNT       PIC 9(2).
    05  RECENT-TXN OCCURS 5 TIMES.
        10  TXN-DATE    PIC X(10).
        10  TXN-AMOUNT  PIC S9(7)V99 COMP-3.
The JSON an API returns
{
  "accountId": "00412789",
  "name": "Asha Rao",
  "balance": 1520.75,
  "status": "active",
  "recentTransactions": [
    { "date": "2026-09-30", "amount": -45.10 },
    { "date": "2026-09-28", "amount": 1200.00 }
  ]
}

Mapping rules

COBOLJSONWatch out for
PIC X(n)stringTrailing spaces — trim them
PIC 9 / COMP-3numberImplied decimal point (V99); precision of large amounts
OCCURS n TIMESarrayReturn only the entries in use, not all n
Single-letter codes such as 'A'readable value such as "active"Agree the code list with consumers
Fields only the program needsleft outNever expose internal or filler fields

Encoding

COBOL data on z/OS is in EBCDIC; JSON on the wire is UTF-8. The API layer converts it. Names with accented letters, and symbols such as €, are where a wrong code page shows up first, so include them in your test data.

Who does the mapping

You rarely write conversion code by hand. Tools generate it from the copybook: z/OS Connect has a mapping editor, CICS provides the JSON assistant utilities, and Enterprise COBOL can convert directly with JSON GENERATE and JSON PARSE. Your job is to choose the field names and rules and to test the edge cases.

Copybook to JSON, field by field

COBOL → JSONWhat it means
05 ACCT-ID PIC X(8).
"accountId": "00412789" — a string, with trailing spaces trimmed.
05 ACCT-BALANCE PIC S9(9)V99 COMP-3.
"balance": 1520.75 — an exact decimal; the V99 becomes the decimal point.
05 ACCT-STATUS PIC X.
"status": "active" — a one-letter code mapped to a readable word.
05 RECENT-TXN OCCURS 5 TIMES.
"recentTransactions": [ … ] — an array of only the entries that are filled.

Try it yourself

TRY IT YOURSELF

A field defined PIC S9(9)V99 holds the digits 152075. What value should the JSON contain?

Show a hint

V99 means two digits after an implied decimal point.

Show the solution

1520.75

Common mistakes

Sending every OCCURS entry

A table defined with OCCURS 5 always has five slots. Use the count field and return only the entries that are filled.

Exposing copybook names

Names like ACCT-BAL-X2 mean nothing to app developers and tie the API to the record layout forever. Choose clear names in camelCase.

Forgetting the implied decimal

PIC S9(9)V99 holding 152075 is 1520.75, not 152075. A missed V99 makes every amount a hundred times too big.

What you will see at work

Key terms

Check your understanding.
Take this lesson's quiz and save your progress. Free.

Take the lesson quiz
← REST in plain termsExposing CICS and IMS programs as APIs →