-
Notifications
You must be signed in to change notification settings - Fork 21
Usage zJSON
Creating a JSON document with ABAP data (you can pass any structure/table/complex data, except objects)
SELECT * FROM scarr
INTO TABLE scarr_t
UP TO 3 ROWS.
json_doc = zcl_json_document=>create_with_data( scarr_t ).
json = json_doc->get_json( ).
String "json" now contains:
[
{
"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"
}
]
Append multiple data objects:
SELECT SINGLE * FROM mara
INTO mara_data
WHERE matnr = '100-100'.
SELECT * FROM marc
INTO TABLE marc_data_t
WHERE matnr = '100-100'.
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' ).
json = json_doc->get_json( ).
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
}
]
}
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}
]
}
Create the JSON document class as always
json_doc = zcl_json_document=>create_with_json( json ).
Now get the ABAP data object
TYPES: BEGIN OF ts_data,
scarr TYPE scarr,
sflight TYPE flighttab,
END OF ts_data.
DATA: ls_data TYPE ts_data.
json_doc->get_data( IMPORTING data = ls_data ).
Formated output of a JSON string (for test purposes)
json_doc = zcl_json_document=>create_with_data( scarr_t ).
json_doc->dumps( IMPORTING result = result ).
LOOP AT result
ASSIGNING <line>.
WRITE:/ <line>.
ENDLOOP.
Output
{
"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"
}
]
}
Same example as above, but creation of JSON without "itab".
json_doc = zcl_json_document=>create_with_data(
data = scarr_t
suppress_itab = abap_true ).
The result is now:
[
{
"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"
}
]
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.
lv_json = '[[123,"abc"],[456,"def","another one"]]'.
lo_json_doc = zcl_json_document=>create_with_json( json = lv_json ).
WHILE lo_json_doc->get_next( ) IS NOT INITIAL.
lo_json_doc2 = zcl_json_document=>create_with_json( json = lo_json_doc->get_json( ) ).
WHILE lo_json_doc2->get_next( ) IS NOT INITIAL.
lv_json = lo_json_doc2->get_json( ).
WRITE:/ lv_json.
ENDWHILE.
ENDWHILE.
if you are expecting a large JSON string, please use the following code to prevent unneccessary memory consumption ("call by ref" instead of "call by value")
json_doc->get_json_large(
IMPORTING
json = json
).
Creating a JSON document with JSON data and read content (array in this case)
json_doc = zcl_json_document=>create_with_json( json ).
WHILE json_doc->get_next( ) IS NOT INITIAL.
carrid = json_doc->get_value( 'carrid' ).
carrname = json_doc->get_value( 'carrname' ).
WRITE:/ carrid, carrname.
ENDWHILE.
TYPES: BEGIN OF ts_x,
field TYPE spras,
END OF ts_x.
ls_x-field = 'S'. "Spanish
json_doc->set_use_conversion_exit( abap_false ). "default
json_doc->set_data( ls_x ).
json = json_doc->get_json( ).
Result {"field" :"S"}
json_doc->set_use_conversion_exit( abap_true ).
json_doc->set_data( ls_x ).
json = json_doc->get_json( ).
Result {"field" :"ES"}
json = '{"field" :"S"}'.
json_doc->set_use_conversion_exit( abap_false ). "default
json_doc->set_json( json ).
json_doc->get_data(
IMPORTING
data = ls_x
).
Result ls-x = 'S'
json = '{"field" :"ES"}'.
json_doc->set_use_conversion_exit( abap_true ).
json_doc->set_json( json ).
json_doc->get_data(
IMPORTING
data = ls_x
).
Result ls-x = 'S'
Starting with Basis Release 7.02 SP11 (other Releases: see SAP note 1648418) and Kernel Release 720 patch 116 it is possible to parse JSON with SAP standard transformation. If you don't need special features of the JSON document class (ie. date format, conversion exits) you can use a new class method to convert JSON to ABAP data and vice versa (better performance and less memory consumption).
TYPES: BEGIN OF ts_test,
s TYPE string,
d type d,
END OF ts_test.
DATA json TYPE string.
DATA test TYPE ts_test.
"*--- ABAP -> JSON ---*
test-s = 'aaa " bbb \ ccc < ddd > eee'.
test-d = sy-datlo.
zcl_json_document=>transform_simple(
EXPORTING
data_in = test
IMPORTING
json_out = json
).
WRITE:/ json.
"-> {"RESULT":{"S":"aaa " bbb \ ccc < ddd > eee","D":"2013-02-01"}}
"*--- JSON -> ABAP ---*
CLEAR test.
zcl_json_document=>transform_simple(
EXPORTING
json_in = json
IMPORTING
data_out = test
).
WRITE:/ test-s, test-d.
"-> aaa " bbb \ ccc < ddd > eee 01022013
If data element "boolean" is used, the class now returns real boolean values:
DATA: BEGIN OF ls_test,
yyy TYPE boolean,
xxx TYPE boolean,
END OF ls_test.
ls_test-xxx = abap_true.
DATA(json_doc) = zcl_json_document=>create_with_data( ls_test ).
cl_demo_output=>display( json_doc->get_json( ) ).
-> {"yyy" :false,"xxx" :true}
But the old handling is still possible:
DATA(json_doc) = zcl_json_document=>create_with_data(
data = ls_test
ignore_boolean = abap_true
).
-> {"yyy" :"","xxx" :"X"}
We now can pass JSON boolean values to the JSON document class:
DATA: BEGIN OF ls_test,
yyy TYPE boolean,
xxx TYPE boolean,
END OF ls_test.
DATA(json_doc) = zcl_json_document=>create_with_json( '{"yyy" : false, "xxx" : true}' ).
json_doc->get_data( IMPORTING data = ls_test ).
cl_demo_output=>display( ls_test ).
-> test-f1 = "" test-f2 = "X"
TYPES: BEGIN OF ts_test,
f1 TYPE boolean,
f2 TYPE string,
END OF ts_test.
DATA test TYPE ts_test.
DATA test_ref TYPE REF TO data.
test-f1 = abap_true.
test-f2 = 'And another Test'.
GET REFERENCE OF test INTO test_ref.
DATA(json_doc) = zcl_json_document=>create_with_data( test_ref ).
cl_demo_output=>display( json_doc->get_json( ) ).
-> {"f1" :true,"f2" :"And another Test"}
NUMC fields are treated like strings (surrounded by quotes) -> attention: this is an incompatible change!
If (like in previous versions) no quotes are required, the parameter "numc_as_numeric" must be set to TRUE:
DATA tnumc TYPE n LENGTH 4 VALUE '10'.
json_doc = zcl_json_document=>create_with_data( tnumc ).
-> "0010"
json_doc = zcl_json_document=>create_with_data(
data = tnumc
numc_as_numeric = abap_true
).
-> 10
TYPES: BEGIN OF local_test,
field1 TYPE string,
field2 TYPE string,
END OF local_test.
DATA input TYPE REF TO data.
DATA output TYPE REF TO data.
FIELD-SYMBOLS <inp> TYPE local_test.
CREATE DATA input TYPE local_test.
ASSIGN input->* TO <inp>.
<inp>-field1 = 'Dref string 1'.
<inp>-field2 = 'Dref string 2'.
DATA(json_doc) = zcl_json_document=>create_with_data( input ).
DATA(json) = json_doc->get_json( ).
json_doc->set_json( json ).
"*--- Test 1: without creating data field -> returns a string ---*
FIELD-SYMBOLS <ref1> TYPE string.
json_doc->get_data(
IMPORTING
data = output
).
ASSIGN output->* TO <ref1>.
cl_demo_output=>display( <ref1> ).
-> {"field1" :"Dref string 1","field2" :"Dref string 2"}
"*--- Test 2: with creating data field -> returns the structured values ---*
FIELD-SYMBOLS <ref2> TYPE local_test.
CLEAR output.
CREATE DATA output TYPE local_test.
json_doc->get_data(
IMPORTING
data = output
).
ASSIGN output->* TO <ref2>.
cl_demo_output=>display( <ref2> ).
-> FIELD1 = Dref string 1 -> FIELD2 = Dref string 2
DATA: BEGIN OF local_test,
field_number1 TYPE string,
field_number2 TYPE string,
END OF local_test.
DATA(json) = zcl_json_document=>create_with_data(
data = local_test
replace_underscore = abap_true
)->get_json( ).
Result
{
"field-number1" :"",
"field-number2" :""
}
DATA: BEGIN OF test,
field_one TYPE string,
field__two TYPE string,
__field__three TYPE string,
END OF test.
DATA(json) = zcl_json_document=>create_with_data(
data = test
replace_underscore = abap_true
replace_double_underscore = abap_true
)->get_json( ).
Result
{
"field-one":"",
"fieldTwo":"",
"FieldThree":""
}
ABAP field names are case insensitive
Examples: ABAP -> JSON
DATA: BEGIN OF local_test,
field_number1 TYPE string VALUE '111',
field_number2 TYPE string VALUE '222',
field_number3 TYPE string VALUE '333',
END OF local_test.
DATA(json) = zcl_json_document=>create_with_data(
data = local_test
name_mappings = VALUE #(
(
abap_name = 'field_number2'
json_name = 'ThisIsATheJSONFieldName'
)
(
abap_name = 'field_number3'
json_name = 'FieldNameThree'
)
)
)->get_json( ).
Result:
{
"field_number1":"111",
"ThisIsATheJSONFieldName":"222",
"FieldNameThree":"333"
}
JSON -> ABAP
DATA: BEGIN OF local_test,
field_number1 TYPE string VALUE '111',
field_number2 TYPE string VALUE '222',
field_number3 TYPE string VALUE '333',
END OF local_test.
DATA json type string.
json = '{' &&
' "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 = local_test ).
cl_demo_output=>display( local_test ).
CATCH zcx_json_document.
ENDTRY.
Result:
FIELD_NUMBER1 FIELD_NUMBER2 FIELD_NUMBER3
111 222 333