Hi Greg,
Thanks for providing some more details, that helped.
I'll approach this answer two ways: (1) will be to use the 'path'
option to only get the 'value' subfield from the json document. (2)
will be to get the whole document and deal with the fields like
@odata.context and @odata.nextLink.
FIRST SOLUTION (USING PATH):
One difference between XML and JSON is that the document element (the
one that surrounds all other content in the document) in JSON does not
have a name. This is not unique to JSON, by the way, there are lots of
formats that don't give names to internal elements.
Unfortunately, IBM didn't consider this possibility when they created
DATA-INTO. I'm guessing they pretty much copied XML-INTO. For this
reason, the "path=" option in data-into does not understand an unnamed
elements, which IMHO, is its biggest problem.
YAJLINTO works around this by giving you the option to assign a name to
the document element. It won't be assigned in the document itself, but
YAJLINTO will trick data-into into thinking it is if you tell it to.
This is done by passing a small JSON document to the %PARSER BIF to tell
it the name of the document element.
%parser('YAJLINTO': '{ "document_name": "doc"}');
With this option, the outermost element (aka the document element) is
now named "doc", so you can use a path like this: 'path=doc/value'
Using that solution results in code like this:
dcl-c RPGOPTS const('doc=file case=convert allowextra=yes
path=doc/value');
dcl-c YAJLOPTS const('{ "document_name": "doc" }');
dcl-ds *n psds;
count int(20) pos(372);
end-ds;
dcl-ds Orders dim(20) qualified;
ID char(10);
ProfileID char(10);
SiteID char(15);
SiteName char(50);
SiteAccountID char(10);
SiteOrderID char(128);
// + more stuff
end-ds;
dcl-s i int(10);
Data-Into Orders %data('orders_test.json' : RPGOPTS )
%parser('YAJLINTO' : YAJLOPTS);
for i = 1 to count;
dsply orders(i).ID;
endfor;
SECOND SOLUTION (READ ENTIRE DOCUMENT)
As far as I can tell the only thing giving you trouble with reading the
whole document is that you don't know how to define things that match
json fields that have names that aren't allowed in RPG. DATA-INTO (as
well as XML-INTO) provide an option called "case=convert" for exactly
that reason. You can read how this option works here:
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzasd/caseopt.htm
In the example of @odata.context anything not A-Z or 0-9 will be
translated to underscores, so you'll have '_odata_context', and then
because you can't start a variable with an underscore, RPG will remove
the leading underscore resulting in 'odata_context'. So if you want to
use that field in your program, just use case=convert, and name the
field 'odata_context'
dcl-c RPGOPTS const('doc=file case=convert allowextra=yes +
countprefix=count_');
dcl-ds json qualified;
odata_context varchar(128);
count_value int(10);
dcl-ds value dim(20);
ID char(10);
ProfileID char(10);
SiteID char(15);
SiteName char(50);
SiteAccountID char(10);
SiteOrderID char(128);
// + more stuff
end-ds;
odata_nextlink varchar(128);
end-ds;
dcl-s i int(10);
Data-Into json %data('orders_test.json' : RPGOPTS )
%parser('YAJLINTO');
for i = 1 to json.count_value;
dsply json.value(i).ID;
endfor;
I can name at least 4 ways that XML is more complicated than JSON...
but, I think your statement that XML is easier is only based on you
being frustrated with the PATH thing, so I'll spare you.
-SK
On 6/7/2019 4:06 PM, Greg Wilburn wrote:
Yes... I see exactly what you're saying.
But I can't have a field named "@odata.context" and "value" seems like an "envelope" around all of the data. There is another "@odata.next" at the end of value object. The actual structure for each individual order object doesn't seem to have a "name".
As an Amazon Associate we earn from qualifying purchases.