Skip to content
Uwe Fetzer edited this page Jan 22, 2021 · 12 revisions

Usage (Release 0.2.x)

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"
}
]

New in version 0.2.1

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
}
]
}

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}
]
}

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 ).

New in version 0.2.6

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"
    	}
	]
}

New in version 0.2.9

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"
	}
]

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.

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.

New in release 0.2.13

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.

Working with conversion exits (new in Release 0.2.14)

	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'

Simple transformation (new in Release 0.2.17)

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

Handling of boolean values (new in Release 0.2.24)

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"}

Handling of boolean values (new in Release 0.2.25)

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"

Handling of data reference objects (new in Release 0.2.25)

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"}

Handling of NUMC fields (new in Release 0.2.26)

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

Handling of data references (new in Release 0.2.27)

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

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

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" :""
}

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

    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":""
}

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

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