Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
UweFetzer_se38
Active Contributor
Since my JSON parsing class zJSON is celebrating its 10th anniversary this year and its “successor” /ui2/cl_json - in combination with /ui2/cl_data_access - now has (nearly) all the needed functions built in, it’s time to retire (the class of course, not me unfortunately).

To make the farewell easier for us all, I’ve created a little “How To Migrate”, where I’ll compare the examples of the zJSON Wiki ( se38/zJSON Wiki · GitHub ) with the new solution.

Usage (Release 0.2.x)


Creating a JSON document with ABAP data (you can pass any structure/table/complex data, except objects)

 














zJSON /ui2/cl_json

SELECT * FROM scarr
INTO TABLE @DATA(scarr_t)
UP TO 3 ROWS.

DATA(json) = zcl_json_document=>create_with_data( scarr_t
)->get_json( ).

 
SELECT * FROM scarr
INTO TABLE @DATA(scarr_t)
UP TO 3 ROWS.

DATA(json) = /ui2/cl_json=>serialize( scarr_t ).

Result
[
{
"mandt" :"001",
"carrid" :"AA",
"carrname" :"American Airlines",
"currcode" :"USD",
"url" :"http://www.aa.com"
},
{
"mandt" :"001",
"carrid" :"AB",
"carrname" :"Air Berlin",
"currcode" :"EUR",
"url" :"http://www.airberlin.de"
},
{
"mandt" :"001",
"carrid" :"AC",
"carrname" :"Air Canada",
"currcode" :"CAD",
"url" :"http://www.aircanada.ca"
}
]


New in version 0.2.1


Append multiple data objects














zJSON /ui2/cl_json

SELECT SINGLE * FROM mara
INTO @DATA(mara_data)
WHERE matnr = '100-100'.

SELECT * FROM marc
INTO TABLE @DATA(marc_data_t)
WHERE matnr = '100-100'.

DATA(json_doc) = zcl_json_document=>create( ).

json_doc->append_data( data = mara_data iv_name = 'MARA' ).
json_doc->append_data( data = marc_data_t iv_name = 'MARC' ).

DATA(json) = json_doc->get_json( ).

Not (yet) implemented directly (?)Workaround:
TYPES t_marc TYPE STANDARD TABLE OF marc WITH EMPTY KEY.

DATA: BEGIN OF material,
mara TYPE mara,
marc TYPE t_marc,
END OF material.

SELECT SINGLE * FROM mara
INTO @material-mara
WHERE matnr = '100-100'.

SELECT * FROM marc
INTO TABLE @material-marc
WHERE matnr = '100-100'.

DATA(json) = /ui2/cl_json=>serialize( material ).

Result
{
"MARA":
{
"mandt" :"800",
"matnr" :"100-100",
"ersda" :"19941107",
"ernam" :"BALLER",
..
"fiber_part5" :"000",
"fashgrd" :""
},
"MARC":
[
{
"mandt" :"800",
"matnr" :"100-100",
"werks" :"1000",
"pstat" :"VEDPALSQGF",
..
"ref_schema" :"",
"min_troc" :"000",
"max_troc" :"000",
"target_stock" :0.000
}
]
}


New in version 0.2.3


Get ABAP data object from JSON string:

Assume our JSON contains the following data (a structure object and a table)
{
"scarr" :
{"mandt" :"001",
"carrid" :"LH",
"carrname" :"Lufthansa",
"currcode" :"EUR",
"url" :"http://www.lufthansa.com"
},
"sflight" :
[{"mandt" :"001",
"carrid" :"LH",
"connid" :"0400",
"fldate" :"20100821",
..
"seatsocc_f" :10},
{"mandt" :"001",
"carrid" :"LH",
"connid" :"0400",
"fldate" :"20100918",
..
"seatsocc_f" :10}
]
}

DATA: BEGIN OF flight_data,
scarr TYPE scarr,
sflight TYPE flighttab,
END OF flight_data.

 











zJSON /ui2/cl_json

zcl_json_document=>create_with_json( json 
)->get_data( IMPORTING data = flight_data ).


/ui2/cl_json=>deserialize(
EXPORTING
json = json
CHANGING
data = flight_data
).


New in version 0.2.6


Formatted output of a JSON string (for test purposes)














zJSON /ui2/cl_json

zcl_json_document=>create_with_data( flight_data 
)->dumps( IMPORTING result = DATA(result) ).

LOOP AT result REFERENCE INTO data(line).
WRITE:/ line->*.
ENDLOOP.

Not (yet) implemented directly (?)Workaround:
DATA(json) = /ui2/cl_json=>serialize( flight_data ).
cl_demo_output=>display_json( json ).

Result
{
"itab" :
[
{
"mandt" : 001,
"carrid" : "AA",
"carrname" : "American Airlines",
"currcode" : "USD",
"url" : "http://www.aa.com"
},
{
"mandt" : 001,
"carrid" : "AB",
"carrname" : "Air Berlin",
"currcode" : "EUR",
"url" : "http://www.airberlin.de"
},
{
"mandt" : 001,
"carrid" : "AC",
"carrname" : "Air Canada",
"currcode" : "CAD",
"url" : "http://www.aircanada.ca"
}
]
}


Working with nested arrays/tables (new in version 0.2.10)


Please note: the JSON document class is only able to keep one array and one JSON data string in memory. If you have to parse a nested array, you need one JSON class instance per nested array.
DATA(json) = `[[123,"abc"],[456,"def","another one"]]`.















zJSON /ui2/cl_json

DATA(json_doc) = zcl_json_document=>create_with_json( json = json ).

WHILE json_doc->get_next( ) IS NOT INITIAL.
DATA(json_doc2) = zcl_json_document=>create_with_json(
json = json_doc->get_json( ) ).

WHILE json_doc2->get_next( ) IS NOT INITIAL.
json = json_doc2->get_json( ).
WRITE:/ json.
ENDWHILE.

ENDWHILE.

 
DATA target TYPE REF TO data.

/ui2/cl_json=>deserialize(
EXPORTING json = json
CHANGING data = target ).

FIELD-SYMBOLS <table1> TYPE ANY TABLE.
FIELD-SYMBOLS <line1> TYPE any.

FIELD-SYMBOLS <table2> TYPE ANY TABLE.
FIELD-SYMBOLS <line2> TYPE any.
FIELD-SYMBOLS <field> TYPE any.

ASSIGN target->* TO <table1>.

LOOP AT <table1> ASSIGNING <line1>.

ASSIGN <line1>->* TO <table2>.

LOOP AT <table2> ASSIGNING <line2>.
ASSIGN <line2>->* TO <field>.
WRITE:/ <field>.
ENDLOOP.

ENDLOOP.

Result
123
abc
456
def
another one


New in release 0.2.13


Creating a JSON document with JSON data and read content (array in this case)
DATA(json) = `[{"carrid":"LH", "carrname":"Lufthansa"},{"carrid":"UA", "carrname":"United"}]`.















zJSON /ui2/cl_json

DATA(json_doc) = zcl_json_document=>create_with_json( json ).

WHILE json_doc->get_next( ) IS NOT INITIAL.

DATA(carrid) = json_doc->get_value( 'carrid' ).
DATA(carrname) = json_doc->get_value( 'carrname' ).

WRITE:/ carrid, carrname.

ENDWHILE.

 
DATA target TYPE REF TO data.

/ui2/cl_json=>deserialize(
EXPORTING json = json
CHANGING data = target ).

FIELD-SYMBOLS <table> TYPE ANY TABLE.
FIELD-SYMBOLS <line> TYPE any.

ASSIGN target->* TO <table>.

LOOP AT <table> ASSIGNING <line>.

DATA(data_access) = /ui2/cl_data_access=>create( ir_data = <line> ).

DATA carrid TYPE string.
DATA carrname TYPE string.

data_access->at( 'carrid' )->value( IMPORTING ev_data = carrid ).
data_access->at( 'carrname' )->value( IMPORTING ev_data = carrname ).

WRITE:/ carrid, carrname.

ENDLOOP.

Result
LH Lufthansa
UA United


New option: replace underscores in fieldnames with hyphen (new in Release 2.32)


DATA: BEGIN OF struc,
field_number1 TYPE string,
field_number2 TYPE string,
END OF struc.















zJSON /ui2/cl_json

DATA(json) = zcl_json_document=>create_with_data(
data = struc
replace_underscore = abap_true )->get_json( ).

not (yet) implemented
Result
{
"field-number1" :"",
"field-number2" :""
}


New option: replace double underscores in fieldnames with CamelCase (new in Release 2.33) and vice versa




















zJSON /ui2/cl_json

DATA: BEGIN OF struc1,
field__two TYPE string,
__field__three TYPE string,
END OF struc1.

struc1 = VALUE #( field__two = '2' __field__three = '3' ).
DATA(json) = zcl_json_document=>create_with_data(
data = struc1
replace_double_underscore = abap_true )->get_json( ).

not (yet) implemented
Result
{
"fieldTwo" :"2",
"FieldThree" :"3"
}

not implemented
DATA: BEGIN OF struc2,
field_two TYPE string,
field_three TYPE string,
END OF struc2.

/ui2/cl_json=>deserialize(
EXPORTING json = json
pretty_name = /ui2/cl_json=>pretty_mode-camel_case
CHANGING data = struc2 ).


Mapping fieldnames between ABAP and JSON (new in Release 2.34)


ABAP field names are case insensitive
DATA: BEGIN OF struc,
field_number1 TYPE string VALUE '111',
field_number2 TYPE string VALUE '222',
field_number3 TYPE string VALUE '333',
END OF struc.






















zJSON /ui2/cl_json

DATA(json) = zcl_json_document=>create_with_data(
data = struc
name_mappings = VALUE #(
(
abap_name = 'field_number2'
json_name = 'ThisIsATheJSONFieldName'
)
(
abap_name = 'field_number3'
json_name = 'FieldNameThree'
)
)
)->get_json( ).

 
DATA(json) = /ui2/cl_json=>serialize(
data = struc
name_mappings = VALUE #(
(
abap = 'field_number2'
json = 'ThisIsATheJSONFieldName'
)
(
abap = 'field_number3'
json = 'FieldNameThree'
)
)
).

Result
{
"field_number1":"111",
"ThisIsATheJSONFieldName":"222",
"FieldNameThree":"333"
}


DATA(json_doc) = zcl_json_document=>create_with_json(
json = json
name_mappings = VALUE #(
(
abap_name = 'FIELD_NUMBER2'
json_name = 'ThisIsATheJSONFieldName'
)
(
abap_name = 'field_number3'
json_name = 'FieldNameThree'
)
)
).

TRY.
json_doc->get_data( IMPORTING data = struc ).
CATCH zcx_json_document.
ENDTRY.

 
/ui2/cl_json=>deserialize(
EXPORTING
json = json
name_mappings = VALUE #(
(
abap = 'field_number2'
json = 'ThisIsATheJSONFieldName'
)
(
abap = 'field_number3'
json = 'FieldNameThree'
)
)
CHANGING
data = struc
).

Result
STRUC
FIELD_NUMBER1 FIELD_NUMBER2 FIELD_NUMBER3
111 222 333


Thank you alexey.arseniev , sebastian.wolf and your teams for this class and your help. May the class get the new namespace soon, maybe in the next few weeks during the “SAP Developer Code Challenge – Open Source ABAP!😊

As always: Love, Peace and JSON

Cheers, Uwe
1 Comment