The DATA-INTO opcode parses a structured document (JSON, CSV, or any format) into a qualified data structure. It generalizes XML-INTO: where XML-INTO has a built-in XML parser, DATA-INTO has no built-in parser - you name one with %PARSER, and it reports the names and values it finds. RPG performs the name-to-subfield mapping using the same rules and options as XML-INTO.

data-into receiver %data(document : options) %parser(parser : parserOptions);

The parser interface

A parser is a procedure that takes one parameter - the parser-info data structure (QrnDiParm_T) - and reports the document's structure by calling the runtime callback procedures. The compiler recognizes the QrnDi* callbacks by name and binds them to its runtime, so you declare their prototypes inline (or /copy IBM's QRNDTAINTO member) and no service program is required:

dcl-ds QrnDiParm_T qualified template;
  data    pointer;      // pointer to the document bytes
  env     pointer;      // reserved (the callback environment)
  handle  pointer;      // pass as the first argument to every callback
  dataLen uns(10);      // document length in bytes
end-ds;

dcl-pr QrnDiStart       extproc('QrnDiStart');       handle pointer value; end-pr;
dcl-pr QrnDiFinish      extproc('QrnDiFinish');      handle pointer value; end-pr;
dcl-pr QrnDiStartStruct extproc('QrnDiStartStruct'); handle pointer value; end-pr;
dcl-pr QrnDiEndStruct   extproc('QrnDiEndStruct');   handle pointer value; end-pr;
dcl-pr QrnDiReportNameCcsid extproc('QrnDiReportNameCcsid');
  handle pointer value; name pointer value; nameLen uns(10) value; ccsid uns(10) value;
end-pr;
dcl-pr QrnDiReportValueCcsid extproc('QrnDiReportValueCcsid');
  handle pointer value; val pointer value; valLen uns(10) value; ccsid uns(10) value;
end-pr;

The callbacks the compiler binds are: QrnDiStart / QrnDiFinish (bracket the parse), QrnDiStartStruct / QrnDiEndStruct and QrnDiStartArray / QrnDiEndArray (structure and array boundaries), QrnDiReportName / QrnDiReportValue and their ...Ccsid variants (report a field name and its value), QrnDiReportError (abandon the parse with an error), and QrnDiTrace (accepted as a no-op). A name pointer and length identify the reported text. The ccsid a ...Ccsid callback reports is honored when decoding that text into the receiver: 0 is the job CCSID (single-byte, read as-is); 1208/1209 are decoded as UTF-8; 1200/1201/13488/13489 as UTF-16/UCS-2; and 367 (US-ASCII), 819 (ISO-8859-1), 923 (ISO-8859-15), and 1252 (Windows-1252) as their respective single-byte encodings. A reported CCSID outside this set is rejected at run time with status 00352 rather than decoded with a guessed charset. Each callback takes the handle from the parser parameter as its first argument.

Example

dcl-ds info qualified;
  company char(10);
  city    char(10);
end-ds;
dcl-s doc varchar(20) inz('ignored');
dcl-s nm  char(50);
dcl-s val char(50);

data-into info %data(doc : 'case=any') %parser(diParse);
// info.company = 'Acme Inc', info.city = 'Chicago'

dcl-proc diParse;
  dcl-pi *n;
    parm likeds(QrnDiParm_T) const;
  end-pi;
  QrnDiStart(parm.handle);
  QrnDiStartStruct(parm.handle);          // the receiver structure
  nm = 'company';
  QrnDiReportNameCcsid (parm.handle : %addr(nm)  : %len(%trimr(nm))  : 0);
  val = 'Acme Inc';
  QrnDiReportValueCcsid(parm.handle : %addr(val) : %len(%trimr(val)) : 0);
  nm = 'city';
  QrnDiReportNameCcsid (parm.handle : %addr(nm)  : %len(%trimr(nm))  : 0);
  val = 'Chicago';
  QrnDiReportValueCcsid(parm.handle : %addr(val) : %len(%trimr(val)) : 0);
  QrnDiEndStruct(parm.handle);
  QrnDiFinish(parm.handle);
end-proc;

A reported name matches a subfield using the case option (a lowercase name matches an RPG subfield by default), and a reported value is converted to the subfield's type (so a numeric subfield receives a numeric value). The strict allowmissing/allowextra rules are enforced exactly as for XML-INTO.

%DATA options

The %data options parallel XML-INTO's %xml options: case (lower, upper, any, convert), trim (all, none), allowmissing / allowextra (yes, no), countprefix, path, doc, and ccsid. An unknown option name, a malformed token, or an invalid value is rejected at compile time (TRN2401).

Supported: a bound-procedure parser reporting a flat qualified data structure (scalar subfields), with the %DATA options above. Reporting into arrays and nested data structures, the %HANDLER array form, and doc=file documents are not supported.