JSON (JavaScript Object Notation) ist das Standardformat für REST-APIs und moderne Integrationen. ABAP bietet mehrere Möglichkeiten zur JSON-Verarbeitung: /ui2/cl_json, XCO-Bibliotheken und native ABAP-Transformation.
Übersicht der Methoden
| Methode | Verfügbarkeit | Empfehlung |
|---|---|---|
/ui2/cl_json | Ab 7.40 | Einfach, weit verbreitet |
| XCO (Cloud) | ABAP Cloud | Modern, typsicher |
| Simple Transformation | Alle | Performant, mehr Aufwand |
| sXML | Alle | Low-Level |
/ui2/cl_json – Der Klassiker
1. Struktur zu JSON (Serialisierung)
TYPES: BEGIN OF ty_customer, id TYPE i, name TYPE string, email TYPE string, active TYPE abap_bool, END OF ty_customer.
DATA: ls_customer TYPE ty_customer.
ls_customer = VALUE #( id = 1001 name = 'Max Mustermann' email = 'max@example.com' active = abap_true).
" Struktur zu JSON konvertierenDATA(lv_json) = /ui2/cl_json=>serialize( data = ls_customer compress = abap_true " Keine Nullwerte/leere Felder pretty_name = /ui2/cl_json=>pretty_mode-camel_case).
WRITE: / lv_json." {"id":1001,"name":"Max Mustermann","email":"max@example.com","active":true}2. JSON zu Struktur (Deserialisierung)
DATA: lv_json TYPE string.DATA: ls_customer TYPE ty_customer.
lv_json = '{"id":1001,"name":"Max Mustermann","email":"max@example.com","active":true}'.
" JSON zu Struktur konvertieren/ui2/cl_json=>deserialize( EXPORTING json = lv_json pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_customer).
WRITE: / 'ID:', ls_customer-id.WRITE: / 'Name:', ls_customer-name.WRITE: / 'E-Mail:', ls_customer-email.3. Interne Tabelle zu JSON
DATA: lt_customers TYPE TABLE OF ty_customer.
lt_customers = VALUE #( ( id = 1 name = 'Müller' email = 'mueller@test.de' active = abap_true ) ( id = 2 name = 'Schmidt' email = 'schmidt@test.de' active = abap_true ) ( id = 3 name = 'Weber' email = 'weber@test.de' active = abap_false )).
DATA(lv_json) = /ui2/cl_json=>serialize( data = lt_customers compress = abap_true pretty_name = /ui2/cl_json=>pretty_mode-camel_case).
WRITE: / lv_json." [{"id":1,"name":"Müller",...},{"id":2,...},{"id":3,...}]4. JSON-Array zu Tabelle
DATA: lv_json TYPE string.DATA: lt_customers TYPE TABLE OF ty_customer.
lv_json = '[{"id":1,"name":"A"},{"id":2,"name":"B"},{"id":3,"name":"C"}]'.
/ui2/cl_json=>deserialize( EXPORTING json = lv_json CHANGING data = lt_customers).
LOOP AT lt_customers INTO DATA(ls_cust). WRITE: / ls_cust-id, ls_cust-name.ENDLOOP.5. Pretty-Name Optionen
DATA: ls_data TYPE ty_customer.
" Original ABAP-Namen (UPPERCASE)DATA(lv_json1) = /ui2/cl_json=>serialize( data = ls_data pretty_name = /ui2/cl_json=>pretty_mode-none)." {"ID":1001,"NAME":"Max",...}
" camelCaseDATA(lv_json2) = /ui2/cl_json=>serialize( data = ls_data pretty_name = /ui2/cl_json=>pretty_mode-camel_case)." {"id":1001,"name":"Max",...}
" Lowercase mit UnterstrichenDATA(lv_json3) = /ui2/cl_json=>serialize( data = ls_data pretty_name = /ui2/cl_json=>pretty_mode-low_case)." {"id":1001,"name":"Max",...}6. Verschachtelte Strukturen
TYPES: BEGIN OF ty_address, street TYPE string, city TYPE string, zip TYPE string, END OF ty_address.
TYPES: BEGIN OF ty_person, name TYPE string, age TYPE i, address TYPE ty_address, END OF ty_person.
DATA: ls_person TYPE ty_person.
ls_person = VALUE #( name = 'Max' age = 30 address = VALUE #( street = 'Hauptstraße 1' city = 'Berlin' zip = '10115' )).
DATA(lv_json) = /ui2/cl_json=>serialize( data = ls_person pretty_name = /ui2/cl_json=>pretty_mode-camel_case).
" {"name":"Max","age":30,"address":{"street":"Hauptstraße 1","city":"Berlin","zip":"10115"}}7. Formatierte Ausgabe (Pretty Print)
DATA(lv_json) = /ui2/cl_json=>serialize( data = ls_customer pretty_name = /ui2/cl_json=>pretty_mode-camel_case format_output = abap_true " Eingerückt/formatiert).
" {" "id": 1001," "name": "Max Mustermann"," "email": "max@example.com"" }8. Generisches Parsen (ohne Typ)
DATA: lv_json TYPE string.DATA: lr_data TYPE REF TO data.FIELD-SYMBOLS: <data> TYPE any.
lv_json = '{"name":"Max","age":30,"items":[1,2,3]}'.
" Generisch parsen/ui2/cl_json=>deserialize( EXPORTING json = lv_json CHANGING data = lr_data).
" Ergebnis ist eine dynamische StrukturASSIGN lr_data->* TO <data>.9. Name-Mapping
TYPES: BEGIN OF ty_abap_struct, customer_id TYPE i, customer_name TYPE string, END OF ty_abap_struct.
DATA: ls_data TYPE ty_abap_struct.
" JSON mit anderen FeldnamenDATA: lv_json TYPE string VALUE '{"customerId":1,"customerName":"Test"}'.
" Name-Mapping über PRETTY_NAME/ui2/cl_json=>deserialize( EXPORTING json = lv_json pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_data).
WRITE: / ls_data-customer_id, ls_data-customer_name.XCO – ABAP Cloud
10. XCO JSON Serialisierung
" Nur in ABAP Cloud / Steampunk verfügbarDATA: ls_customer TYPE ty_customer.
ls_customer = VALUE #( id = 1 name = 'Test' email = 'test@test.de' ).
" SerialisierenDATA(lv_json) = xco_cp_json=>data->from_abap( ls_customer )->apply( VALUE #( ( xco_cp_json=>transformation->camel_case ) ) )->to_string( ).
" Deserialisierenxco_cp_json=>data->from_string( lv_json )->apply( VALUE #( ( xco_cp_json=>transformation->underscore_case ) ) )->write_to( REF #( ls_customer ) ).Simple Transformation
11. JSON mit Simple Transformation
" Transformation Z_JSON_CUSTOMER erstellen (STRANS)
" <?sap.transform simple?>" <tt:transform xmlns:tt="http://www.sap.com/transformation-templates"" template="main">" <tt:root name="CUSTOMER"/>" <tt:template>" <object>" <str name="id"><tt:value ref="CUSTOMER.ID"/></str>" <str name="name"><tt:value ref="CUSTOMER.NAME"/></str>" </object>" </tt:template>" </tt:transform>
DATA: ls_customer TYPE ty_customer, lv_json TYPE string.
ls_customer = VALUE #( id = 1 name = 'Max' ).
" ABAP zu JSONCALL TRANSFORMATION z_json_customer SOURCE customer = ls_customer RESULT XML lv_json OPTIONS data_refs = 'embedded'.
" JSON zu ABAPCALL TRANSFORMATION z_json_customer SOURCE XML lv_json RESULT customer = ls_customer.Praktische Beispiele
12. REST-API Aufruf
DATA: lv_response TYPE string, ls_result TYPE ty_api_response.
" HTTP-RequestDATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = cl_http_destination_provider=>create_by_url( 'https://api.example.com' )).
DATA(lo_request) = lo_client->get_http_request( ).lo_request->set_uri_path( '/api/customers/1' ).
DATA(lo_response) = lo_client->execute( if_web_http_client=>get ).lv_response = lo_response->get_text( ).
" JSON Response parsen/ui2/cl_json=>deserialize( EXPORTING json = lv_response CHANGING data = ls_result).
lo_client->close( ).13. JSON POST-Request
TYPES: BEGIN OF ty_request, action TYPE string, payload TYPE string, END OF ty_request.
DATA: ls_request TYPE ty_request.
ls_request = VALUE #( action = 'create' payload = 'test data').
" Request-Body erstellenDATA(lv_json_body) = /ui2/cl_json=>serialize( data = ls_request pretty_name = /ui2/cl_json=>pretty_mode-camel_case).
" HTTP POSTDATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = cl_http_destination_provider=>create_by_url( 'https://api.example.com' )).
DATA(lo_request) = lo_client->get_http_request( ).lo_request->set_uri_path( '/api/process' ).lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ).lo_request->set_text( lv_json_body ).
DATA(lo_response) = lo_client->execute( if_web_http_client=>post ).14. Fehlerbehandlung
DATA: lv_json TYPE string VALUE '{"invalid json'.DATA: ls_data TYPE ty_customer.
TRY. /ui2/cl_json=>deserialize( EXPORTING json = lv_json CHANGING data = ls_data ). CATCH cx_sy_move_cast_error INTO DATA(lx_error). WRITE: / 'JSON-Parsing-Fehler:', lx_error->get_text( ).ENDTRY.15. Datum/Zeit in JSON
TYPES: BEGIN OF ty_event, name TYPE string, event_date TYPE d, event_time TYPE t, timestamp TYPE timestamp, END OF ty_event.
DATA: ls_event TYPE ty_event.
ls_event = VALUE #( name = 'Meeting' event_date = sy-datum event_time = sy-uzeit timestamp = utclong_current( )).
" Standard: Datum als YYYYMMDDDATA(lv_json) = /ui2/cl_json=>serialize( data = ls_event pretty_name = /ui2/cl_json=>pretty_mode-camel_case).
" Für ISO-Format: Eigene Konvertierung nötig16. Arrays von primitiven Typen
DATA: lt_ids TYPE TABLE OF i.
lt_ids = VALUE #( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ).
DATA(lv_json) = /ui2/cl_json=>serialize( data = lt_ids ).WRITE: / lv_json. " [1,2,3,4,5]
" ZurückDATA: lt_parsed TYPE TABLE OF i./ui2/cl_json=>deserialize( EXPORTING json = lv_json CHANGING data = lt_parsed).17. Null-Werte behandeln
TYPES: BEGIN OF ty_nullable, name TYPE string, value TYPE i, END OF ty_nullable.
DATA: ls_data TYPE ty_nullable.
ls_data = VALUE #( name = 'Test' ). " value bleibt initial (0)
" Mit compress = true: Initialwerte weglassenDATA(lv_compressed) = /ui2/cl_json=>serialize( data = ls_data compress = abap_true)." {"name":"Test"}
" Ohne compress: Alle FelderDATA(lv_full) = /ui2/cl_json=>serialize( data = ls_data compress = abap_false)." {"name":"Test","value":0}18. Boolean-Werte
TYPES: BEGIN OF ty_flags, enabled TYPE abap_bool, visible TYPE abap_bool, END OF ty_flags.
DATA: ls_flags TYPE ty_flags.
ls_flags = VALUE #( enabled = abap_true visible = abap_false).
DATA(lv_json) = /ui2/cl_json=>serialize( data = ls_flags pretty_name = /ui2/cl_json=>pretty_mode-camel_case).
WRITE: / lv_json. " {"enabled":true,"visible":false}Tipps für API-Integration
" 1. Typen definieren passend zur APITYPES: BEGIN OF ty_api_error, code TYPE string, message TYPE string, END OF ty_api_error.
TYPES: BEGIN OF ty_api_response, success TYPE abap_bool, data TYPE ty_customer, error TYPE ty_api_error, END OF ty_api_response.
" 2. Response verarbeitenDATA(lv_status) = lo_response->get_status( )-code.DATA(lv_body) = lo_response->get_text( ).
DATA: ls_response TYPE ty_api_response./ui2/cl_json=>deserialize( EXPORTING json = lv_body CHANGING data = ls_response).
IF ls_response-success = abap_true. " Erfolg verarbeitenELSE. " Fehler behandeln WRITE: / 'Fehler:', ls_response-error-message.ENDIF.Wichtige Hinweise / Best Practice
/ui2/cl_jsonist der Standard für JSON in klassischem ABAP.- pretty_name für Namenskonvertierung (camelCase, lowercase).
- compress = abap_true entfernt leere/initiale Felder.
- Für ABAP Cloud: XCO-Bibliotheken verwenden.
- Simple Transformations für maximale Performance.
- ABAP-Feldnamen mit Unterstrichen werden zu camelCase konvertiert.
- Testen Sie JSON-Strukturen mit Online-Tools (jsonlint.com).
- Definieren Sie passende ABAP-Typen für API-Responses.
- Fehlerbehandlung mit TRY-CATCH für ungültiges JSON.
- Boolean:
abap_true/abap_falsewird zutrue/false.