Pl1 And JSON Peter Elderon

48
® IBM Software Group © 2013 IBM Corporation PL/I and JSON Spring 2015 Peter Elderon [email protected]

Transcript of Pl1 And JSON Peter Elderon

IBM Software Group | Rational software

3

JSON

Is an alternative to XML

It is simpler and less rich than XML

for example, all JSON text is human readable

This is both a strength and a weakness

IBM Software Group | Rational software

4

JSON

JSON text consists of an array or an object

An array is a comma-delimited list of values enclosed in [ … ]

An object is a comma-delimited list of name-value pairs enclosed in { … }

An array or object may be empty

So [ ] and { } form valid JSON text

Arrays and objects are also values and hence the definition is recursive

IBM Software Group | Rational software

5

JSON

A name (in a name-value pair) is a string

A value is one of

a string

a number

an object

an array

one of the keywords: true, false, null

All JSON text is in UTF-8

IBM Software Group | Rational software

6

JSON

A string is a "-delimited series of UTF-8 characters with \ used to escape

these characters

\

"

/

b, f, n, r, or t (backfeed, formfeed, newline, return, or tab)

u followed by 4 hex digits

So, the value PL/I is held as "PL\/I"

IBM Software Group | Rational software

7

JSON

A number is - essentially – one of the following with possibly a leading

minus sign

an integer (i.e. a series of digits)

a decimal number (i.e. a series of digits with a decimal point)

a floating-point number (i.e. one of the above followed by E (or e) and a possibly

signed series of digits)

Leading zeros are not allowed except when the number consists of exactly

one zero before an optional decimal point or exponent

IBM Software Group | Rational software

8

JSON

The precise syntax rules for a number are given by

IBM Software Group | Rational software

9

JSON

Since arrays and object are themselves values, recursion is possible, e.g.

{ "passes“ : 3,

"data“ :

[

{ "name“ : "Mather", "elevation“ : 12100 }

, { "name“ : "Pinchot", "elevation“ : 12130 }

, { "name“ : "Glenn", "elevation“ : 11940 }

]

}

Whitespace is insignificant except inside strings (and is invalid in numbers)

IBM Software Group | Rational software

11

Functions like those provided for XML

We provide a series of built-in functions that support

Validating JSON text

Generating JSON text

Parsing JSON text

IBM Software Group | Rational software

12

Validating JSON text

The jsonValid built-in function validates the json text of a specified size at a

given address

If valid, zero is returned

Otherwise the index of the first invalid byte is returned

IBM Software Group | Rational software

14

Generating JSON text

all JSON written out will be in UTF-8 with the compiler and library handling

any necessary conversions from EBCDIC

a series of “put” functions is provided and all have a buffer address and

buffer length as their first 2 arguments, and all return the number of bytes

written

attempts to write variables containing data types incompatible with JSON

are flagged at compile time

escaped characters are created as needed

IBM Software Group | Rational software

15

Generating JSON text

The functions allow you to write a variable as complete, valid JSON

Where the variable could be a scalar, an array, or a structure

But the functions also allow you to build some JSON text piecewise

IBM Software Group | Rational software

16

Put value

The jsonPutValue writes a JSON value to a buffer

It is probably be the simplest function to use to generate JSON

But a value is not a name-pair – this function writes just the value

IBM Software Group | Rational software

17

jsonPutValue - example

Given

dcl b(3) fixed bin init(2,3,5)

jsonPutValue( p, n, b ) writes this complete, valid JSON text

[2,3,5]

To the buffer of size n at address p

It returns the value 7 (the number of bytes written to p)

IBM Software Group | Rational software

18

jsonPutValue - example

Given

dcl 1 c, 2 d fixed bin init(2), 2 e fixed bin init(3);

jsonPutValue( p, n, c ) writes this complete, valid JSON text

{ "d" : 2, "e" : 3 }

To the buffer of size n at address p

It returns the value 13 (the number of bytes written to p)

IBM Software Group | Rational software

19

Put value

You could also use jsonPutValue to write a string or number to a buffer

So jsonPutValue( p, n, ‘some text’ ) writes “some text” as UTF8 to the buffer

p of length n and returns the number of bytes written

The return value is greater than the length of the source string if the source

contained characters requiring 2 or more bytes in UTF8

The conversion from EBCDIC to UTF8 is based on the compiler code page

option

IBM Software Group | Rational software

20

Put member

Name-value pairs are also known as members

And Member is shorter than NameValue and hence easier to type and use

jsonPutMember writes a JSON member to a buffer

It is probably be the next simplest function to use to generate JSON

But a member is not by itself valid JSON text

IBM Software Group | Rational software

21

jsonPutMember - example

Given

dcl a fixed bin init(2);

jsonPutMember( p, n, a ) writes this incomplete JSON text

"a" : 2

To the buffer of size n at address p

It returns the value 5 (the number of bytes written to p)

IBM Software Group | Rational software

22

jsonPutMember - example

Given

dcl b(3) fixed bin init(2,3,5);

jsonPutMember( p, n, b ) writes this incomplete JSON text

"b" : [2,3,5]

To the buffer of size n at address p

It returns the value 11 (the number of bytes written to p)

IBM Software Group | Rational software

23

jsonPutMember - example

Given

dcl 1 c, 2 d fixed bin init(2), 2 e fixed bin init(3);

jsonPutMember( p, n, c ) writes this incomplete JSON text

"c" : { "d" : 2, "e" : 3 }

To the buffer of size n at address p

It returns the value 17 (the number of bytes written to p)

IBM Software Group | Rational software

24

jsonPutMember - example

Given

dcl 1 c(2), 2 d fixed bin init(2,3), 2 d fixed bin init(5,7);

jsonPutMember( p, n, c ) writes this incomplete JSON text

"c" : [ { "d" : 2, "e" : 5 }, { "d": 3, "e" : 7 } ]

To the buffer of size n at address p and returns the number of bytes written

Note that is C is an array of structures, and the JSON text also says this

IBM Software Group | Rational software

25

Building JSON text piecewise

To help build JSON piecewise, a series of functions allows you to write any

of the SJON delimiters to a buffer:

jsonPutObjectStart writes {

jsonPutArrayStart writes [

jsonPutComma writes ,

jsonPutColon writes :

jsonPutArrayEnd writes ]

jsonPutObjectStart writes }

This can make your code less cluttered and help you avoid code page

problems since your source never needs to contain these characters

IBM Software Group | Rational software

26

Building JSON text piecewise

So, to write complete, valid JSON text containing the names and values of

the variables x and y, you could write this code

jsize = 0;

jsize += jsonPutObjectStart( addr(buffer)+jsize, length(buffer)-jsize );

jsize += jsonPutMember( addr(buffer)+jsize, length(buffer)-jsize, x );

jsize += jsonPutComma( addr(buffer)+jsize, length(buffer)-jsize );

jsize += jsonPutMember( addr(buffer)+jsize, length(buffer)-jsize, y );

jsize += jsonPutObjectEnd( addr(buffer)+jsize, length(buffer)-jsize );

IBM Software Group | Rational software

27

Building JSON text piecewise

Or if you wanted to write complete, valid JSON text containing only the

values of the variables x and y, you could write this code

jsize = 0;

jsize += jsonPutObjectStart( addr(buffer)+jsize, length(buffer)-jsize );

jsize += jsonPutValue( addr(buffer)+jsize, length(buffer)-jsize, x );

jsize += jsonPutComma( addr(buffer)+jsize, length(buffer)-jsize );

jsize += jsonPutValue( addr(buffer)+jsize, length(buffer)-jsize, y );

jsize += jsonPutObjectEnd( addr(buffer)+jsize, length(buffer)-jsize );

IBM Software Group | Rational software

28

Building JSON text piecewise

Or if you wanted to write complete, valid JSON text containing consisting of the name-value pair "positives" and all the positive values in an array a, you could write this code

jsonPutOjbectStart

jsonPutValue( "positivies" )

jsonPutColon

jsonPutArrayStart

count = 0

do jx = lbound(a) to hbound(a)

if a(jx) > 0 then

do

if count > 0 then

jsonPutComma

jsonPutValue( a(jx) )

count += 1

end

end

jsonPutArrayEnd

jsonPutOjbectEnd

IBM Software Group | Rational software

30

Parsing JSON text

all JSON to be parsed must be in UTF-8 with the compiler and library

handling any necessary conversions to EBCDIC

a series of “get” functions are provided and all have a buffer address and

buffer length as their first 2 arguments, and all return the number of bytes

read

attempts to read variables containing data types incompatible with JSON are

flagged at compile time

whitespace characters are skipped over when found

IBM Software Group | Rational software

31

Parsing JSON text

The functions let you to assign a variable from corresponding JSON

Where the variable could be a scalar, an array, or a structure

But the functions also allow you to parse JSON text piecewise

All these functions are counterparts to the jsonPut functions

IBM Software Group | Rational software

32

Get value and member

jsonGetValue is the counterpart to jsonPutValue

jsonGetMember is the counterpart to jsonPutMember

Usually, both have 3 arguments

But they also accept only 2 arguments in which case the next value (or

member) in the buffer is read over

This for is useful in piecewise parsing

IBM Software Group | Rational software

33

jsonGetValue - example

Given

dcl b(3) fixed bin;

jsonGetValue( p, n, b ) reads this JSON text

[ 2, 3, 5 ]

from the buffer of size n at address p and assign those values to b

It returns a value >= 7 (the number of bytes read including whitespace)

IBM Software Group | Rational software

34

jsonGetValue - example

And given

dcl b(3) fixed bin;

jsonGetValue( p, n, b ) reads this JSON text

[ 2, 5 ]

And assign values only to b(1) and b(2)

IBM Software Group | Rational software

35

jsonGetValue - example

Given

dcl 1 c, 2 d fixed bin, 2 e fixed bin;

jsonGetValue( p, n, c ) reads this JSON text

{ "d" : 2, "e" : 3 }

And assign values to the elements of c

It returns a value >= 13

IBM Software Group | Rational software

36

Get value

You could also use jsonPutValue to read a string or number from a buffer

and assign it to a scalar

So if the next element of some JSON text is the string “elements” and C is a

CHAR(20) VARYING variable, then jsonGetValue( p, n, C ) would

read the UTF8 string “elements”

convert it to EBCDIC

assign the converted value to C and

return the number of bytes read

The conversion to EBCDIC from UTF8 is based on the compiler code page

option

IBM Software Group | Rational software

37

Get member

jsonGetMember reads a JSON member from a buffer

This is the counterpart to jsonPutMember

But as was true in the jsonGetValue examples, the source can omit elements

of the target array or structure

Since a member is incomplete JSON, this function is probably more useful in

parsing JSON piecewise

IBM Software Group | Rational software

38

Parsing JSON text piecewise

To help parse JSON piecewise, a series of functions allows you to read over

whitespace to a specified SJON delimiter in a buffer:

jsonGetObjectStart reads to {

jsonGetArrayStart reads to [

jsonGetComma reads to ,

jsonGetColon reads to :

jsonGetArrayEnd reads to ]

jsonGetObjectStart reads to }

They can also be used to test if the next non-blank is a specified delimiter

(since if it is not, zero will be returned)

IBM Software Group | Rational software

39

Parsing JSON text piecewise

The corresponding jsonPut-delimiter functions (jsonPutObjectStart, etc) are

all inlined with very simple code

These jsonGet delimiter functions are also inlined

But the code is a little less simple - essentially it is

use verify to find the first non-whitespace character

if none, return zero

else if the character matches the delimiter, return bytes scanned

else return zero

IBM Software Group | Rational software

40

Parsing JSON text piecewise

If you wanted to read a JSON object containing name-value pairs for a, b,

and c but assign values only to a and c, you could write this code

jsize = 0;

jsize += jsonGetObjectStart( addr(buffer)+jsize, length(buffer)-jsize );

jsize += jsonGetMember( addr(buffer)+jsize, length(buffer)-jsize, a );

jsize += jsonGetComma( addr(buffer)+jsize, length(buffer)-jsize );

jsize += jsonGetMember( addr(buffer)+jsize, length(buffer)-jsize ); /* only 2 args! */

jsize += jsonGetComma( addr(buffer)+jsize, length(buffer)-jsize );

jsize += jsonGetMember( addr(buffer)+jsize, length(buffer)-jsize, c );

jsize += jsonGetObjectEnd( addr(buffer)+jsize, length(buffer)-jsize );

IBM Software Group | Rational software

41

JSON

Recall this sample JSON text

{ "passes“ : 3,

"data“ :

[

{ "name“ : "Mather", "elevation“ : 12100 }

, { "name“ : "Pinchot", "elevation“ : 12130 }

, { "name“ : "Glenn", "elevation“ : 11940 }

]

}

Suppose it is in a buffer at address p and of length n

IBM Software Group | Rational software

42

JSON

Suppose we had a corresponding PL/I structure

dcl

1 info

2 passes fixed bin(31),

2 data(3),

3 name char(20) varying,

3 elevation fixed bin(31);

Then jsonGetValue( p, n, info ) will by itself fill in the whole structure

And this would work as long as hbound(data) >= 3

IBM Software Group | Rational software

43

JSON

But if the PL/I structure was

dcl

1 info based(q)

2 passes fixed bin(31),

2 data( count refer(passes) ),

3 name char(20) varying,

3 elevation fixed bin(31);

Then the structure could be dynamically assigned as follows

IBM Software Group | Rational software

44

JSON

With the first 2 arguments in every call omitted:

jsonGetObjectStart read over {

jsonGetValue read over “passes”

jsonGetColon read over :

jsonGetValue( count ) read 3 and assign to count

allocate info

jsonGetComma read over ,

jsonGetValue( info.data ) read “data” … and assign it

And it is even simpler if the names in the structure were flipped

IBM Software Group | Rational software

45

JSON

So if the PL/I structure was instead

dcl

1 info based(q)

2 count fixed bin(31),

2 data( passes refer(count) ),

3 name char(20) varying,

3 elevation fixed bin(31);

( now passes sets the REFER object )

IBM Software Group | Rational software

46

JSON

Two fewer built-in references are needed:

jsonGetObjectStart read over {

jsonGetMember( passes ) read “passes” : 3 and assign

allocate info

jsonGetComma read over ,

jsonGetValue( info.data ) read “data” … and assign it

And either way would work no matter how much whitespace was present

IBM Software Group | Rational software

47

Options for JSON

All the examples above used lower-case names in the JSON text

By PL/I default, these should all be upper-case

But the JSON( CASE( ASIS ) ) compiler option allows the names in

the JSON text to be mixed-case – as long as they match the names

as they were declared in the source code

IBM Software Group | Rational software

48

© Copyright IBM Corporation 2008. All rights reserved. The information contained in these materials is provided for informational purposes only, and is provided AS IS without warranty of any kind, express or implied. IBM shall not be responsible for any damages arising out of the use of, or otherwise related to, these materials. Nothing contained in these materials is intended to, nor shall have the effect of, creating any warranties or representations from IBM or its suppliers or licensors, or altering the terms and conditions of the applicable license agreement governing the use of IBM software. References in these materials to IBM products, programs, or services do not imply that they will be available in all countries in which IBM operates. Product release dates and/or capabilities referenced in these materials may change at any time at IBM’s sole discretion based on market opportunities or other factors, and are not intended to be a commitment to future product or feature availability in any way. IBM, the IBM logo, the on-demand business logo, Rational, the Rational logo, and other IBM products and services are trademarks of the International Business Machines Corporation, in the United States, other countries or both. Other company, product, or service names may be trademarks or service marks of others.

Learn more at:

IBM Rational software

IBM Rational Software Delivery Platform

Process and portfolio management

Change and release management

Quality management

Architecture management

Rational trial downloads

developerWorks Rational

IBM Rational TV

IBM Rational Business Partners