APIs, JSON and the Outside World

COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x Β· βœ“ verified by execution on 2026-08-16

For decades, COBOL systems communicated using fixed-width flat files and EBCDIC character sets. Today, they need to communicate with microservices, web browsers, and mobile applications. The lingua franca of modern communication is JSON (JavaScript Object Notation).

Rather than forcing developers to write complex C wrappers or Java bridge layers, modern COBOL compilers introduced native support for parsing and generating JSON payloads. In this lesson, we will explore the JSON GENERATE statement, a powerful tool for serializing COBOL data structures directly into web-ready JSON strings.

To see why COUNT IN is important, predict what happens to the fixed-length PIC X(50) receiving string after the JSON is generated. We will append a <END> marker to reveal any invisible characters:

Predict the output cobol

Read the code. What exactly will it print? Commit to an answer before you look.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. PRED-JSON.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 EMP-REC.
          05 EMP-NAME PIC X(10) VALUE "ALICE".
       01 JSON-OUTPUT PIC X(50).
       PROCEDURE DIVISION.
           JSON GENERATE JSON-OUTPUT FROM EMP-REC.
           DISPLAY JSON-OUTPUT "<END>".
           STOP RUN.
Output
{"EMP-REC":{"EMP-NAME":"ALICE"}}                  <END>

While JSON GENERATE smartly trims trailing spaces from individual values (like β€œALICE”), the target JSON-OUTPUT variable is still a fixed-length COBOL string. This means the resulting JSON payload is padded with spaces up to its 50-byte length! If we send this over a network, we waste bandwidth and risk confusing strict JSON parsers.

Generating Basic JSON

The JSON GENERATE statement takes a source COBOL data item (usually a Group Item) and serializes it into a receiving string.

EMP-REC (COBOL Data) JSON GENERATE {"EMP":123} (JSON String)

Here is a basic example converting an employee record into JSON. Notice the output has trailing spaces because the receiving PIC X(100) variable is fixed-length!

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. JSON-GEN.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 EMP-REC.
          05 EMP-ID   PIC 9(4) VALUE 1234.
          05 EMP-NAME PIC X(10) VALUE "ALICE".
       01 JSON-OUTPUT PIC X(100).
       PROCEDURE DIVISION.
           JSON GENERATE JSON-OUTPUT FROM EMP-REC.
           DISPLAY JSON-OUTPUT.
           STOP RUN.
Output
{"EMP-REC":{"EMP-ID":1234,"EMP-NAME":"ALICE"}}                                                      

Trimming the Output with COUNT IN

Because COBOL strings are fixed-length, sending JSON-OUTPUT directly over a network would transmit 90 bytes of empty space. The COUNT IN phrase solves this by storing the exact length of the generated JSON into a variable. You can then use reference modification (1:JSON-LEN) to extract exactly what you need.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. JSON-CNT.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 EMP-REC.
          05 EMP-ID   PIC 9(4) VALUE 1234.
          05 EMP-NAME PIC X(10) VALUE "ALICE".
       01 JSON-OUTPUT PIC X(100).
       01 JSON-LEN    PIC 9(4).
       PROCEDURE DIVISION.
           JSON GENERATE JSON-OUTPUT FROM EMP-REC COUNT IN JSON-LEN.
           DISPLAY JSON-OUTPUT(1:JSON-LEN).
           STOP RUN.
Output
{"EMP-REC":{"EMP-ID":1234,"EMP-NAME":"ALICE"}}

Exception Handling and Suppressing Fields

What if your receiving field isn’t large enough? JSON GENERATE will trigger an exception condition. You can handle this gracefully with the ON EXCEPTION phrase.

Additionally, you don’t always want to send every piece of data inside a record over an API. The SUPPRESS phrase allows you to exclude specific fields (like sensitive security data) from the generated JSON payload.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. JSON-SUP.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 EMP-REC.
          05 EMP-ID   PIC 9(4) VALUE 1234.
          05 EMP-SSN  PIC X(9) VALUE "SECRET".
       01 JSON-OUT PIC X(100).
       01 JSON-LEN PIC 9(4).
       PROCEDURE DIVISION.
           JSON GENERATE JSON-OUT FROM EMP-REC COUNT IN JSON-LEN
             SUPPRESS EMP-SSN
           END-JSON.
           DISPLAY JSON-OUT(1:JSON-LEN).
           STOP RUN.
Output
{"EMP-REC":{"EMP-ID":1234}}

A Note on OCCURS and JSON PARSE

While JSON GENERATE creates JSON, the JSON PARSE statement does the reverse: turning JSON into COBOL data structures. While this is fully implemented in IBM Enterprise COBOL, in GnuCOBOL 3.x, JSON PARSE is currently a syntax stub. It will compile (with a -Wpending warning) but silently skip parsing at runtime!

Another current limitation in GnuCOBOL 3.x is that JSON GENERATE does not fully support OCCURS arrays yet; it will typically emit only the first element of the array and issue a -Wpending compile warning.

For now, rely on JSON GENERATE for flat COBOL-to-API needs, and use specialized libraries or preprocessors if you need to ingest JSON or serialize complex arrays in GnuCOBOL.

Check yourself

Which COBOL statement is used to serialize a group item into a JSON string?

Reveal answer

JSON GENERATE β€” The JSON GENERATE statement is a standard COBOL feature designed to transform COBOL data into a JSON string.

Why is the COUNT IN phrase crucial when generating JSON in COBOL?

Reveal answer

It captures the exact length of the generated JSON so you can trim trailing spaces from the fixed-length receiving field. β€” COBOL variables are fixed-length, so a PIC X(100) receiving field will pad the JSON with spaces. COUNT IN lets you capture the actual size to substring it later.

What happens if the receiving field for JSON GENERATE is too small to hold the result?

Reveal answer

An exception condition is triggered and JSON-CODE becomes non-zero. β€” If the output exceeds the target area, an exception triggers. You can handle this gracefully with the ON EXCEPTION clause.

Challenges

🐞 Bug Hunt +20 XP

The code below generates JSON but sends trailing spaces. Fix it by capturing the exact length with COUNT IN and using reference modification on the display.

This code runs. It just does the wrong thing. Read it, find the defect, fix it β€” the tests below decide when you are right.

cobol βœ“ solution verified at build time

COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the fixed code should be, then open the solution and compare. The expected output below is real β€” it came from compiling the solution with GnuCOBOL when this page was built.

  • Test 1 β€” expects "{\"EMP-REC\":{\"EMP-NAME\":\"ALICE\"}}<END>"
Need a hint? (βˆ’25% XP)

Add a JSON-LEN variable. Use COUNT IN JSON-LEN. DISPLAY JSON-OUTPUT(1:JSON-LEN) '<END>'.

Show solution (0 XP)
IDENTIFICATION DIVISION.
PROGRAM-ID. CHAL1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 EMP-REC.
   05 EMP-NAME PIC X(10) VALUE "ALICE".
01 JSON-OUTPUT PIC X(50).
01 JSON-LEN    PIC 9(4).
PROCEDURE DIVISION.
    JSON GENERATE JSON-OUTPUT FROM EMP-REC COUNT IN JSON-LEN.
    DISPLAY JSON-OUTPUT(1:JSON-LEN) "<END>".
    STOP RUN.

Challenge 2 +10 XP

What happens if you run `JSON PARSE` in GnuCOBOL 3.x? (Does it error on compile, crash, or compile with a warning but do nothing?)

cobol βœ“ solution verified at build time

COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the fixed code should be, then open the solution and compare. The expected output below is real β€” it came from compiling the solution with GnuCOBOL when this page was built.

  • Test 1 β€” expects "Compiles with warning but does nothing"
Need a hint? (βˆ’25% XP)

It's a syntax stub.

Show solution (0 XP)
IDENTIFICATION DIVISION.
PROGRAM-ID. CHAL2.
PROCEDURE DIVISION.
    DISPLAY "Compiles with warning but does nothing".
    STOP RUN.