XML та JSON
ABAP надає кілька механізмів для роботи з XML і JSON. Вибір залежить від задачі — від повного DOM-дерева до швидкої серіалізації внутрішньої таблиці.
| Інструмент | Коли застосовувати |
|---|---|
iXML (cl_ixml_core) | DOM-доступ: потрібно навігувати деревом, змінювати ноди, підтримувати DTD. |
sXML (cl_sxml_string_writer/reader) | Потоковий парсинг/рендеринг XML і JSON без повного DOM. Швидше і економніше. |
| CALL TRANSFORMATION | Серіалізація/десеріалізація ABAP ↔ XML/JSON через XSLT, Simple Transformation або тотожне перетворення ID. |
XCO (xco_cp_json) | Сучасний fluent-API для JSON у Cloud ABAP. Найпростіший варіант для типових задач. |
/ui2/cl_json | Зручний серіалізатор/десеріалізатор JSON у класичному ABAP, з name mapping і pretty-printing. |
XML через iXML
Section titled “XML через iXML”Бібліотека Integrated XML — повний DOM у пам’яті. Переваги: довільний доступ до нод, підтримка DTD. Мінус: високе споживання пам’яті на великих документах.
Створення XML:
DATA(ixml) = cl_ixml_core=>create( ).DATA(document) = ixml->create_document( ).
" Корінь з namespaceDATA(root) = document->create_element_ns( name = 'abap' prefix = 'asx' ).root->set_attribute_ns( name = 'asx' prefix = 'xmlns' value = 'http://www.sap.com/abapxml' ).root->set_attribute_ns( name = 'version' value = '1.0' ).document->append_child( root ).
DATA(values) = document->create_element_ns( prefix = 'asx' name = 'values' ).root->append_child( values ).
DATA(str_elem) = document->create_element_ns( name = 'STRING' ).values->append_child( str_elem ).str_elem->append_child( document->create_text( 'Hello World' ) ).
" Рендер у xstringDATA xml_out TYPE xstring.ixml->create_renderer( document = document ostream = ixml->create_stream_factory( )->create_ostream_xstring( string = xml_out ))->render( ).Парсинг XML:
DATA(xml_bin) = cl_abap_conv_codepage=>create_out( )->convert( `<root><a>hi</a></root>` ).
DATA(ixml) = cl_ixml_core=>create( ).DATA(doc) = ixml->create_document( ).DATA(parser) = ixml->create_parser( istream = ixml->create_stream_factory( )->create_istream_xstring( string = xml_bin ) document = doc stream_factory = ixml->create_stream_factory( ) ).
IF parser->parse( ) = 0. " Прямий доступ за іменем DATA(elem) = doc->find_from_name( name = `a` ). DATA(val) = elem->get_value( ). " hi
" Ітератор по всіх нодах DATA(iter) = doc->create_iterator( ). DATA(node) = iter->get_next( ). WHILE node IS NOT INITIAL. CASE node->get_type( ). WHEN if_ixml_node=>co_node_element. " ... обробка елемента, атрибутів WHEN if_ixml_node=>co_node_text. " ... текстове значення ENDCASE. node = iter->get_next( ). ENDWHILE.ENDIF.XML через sXML
Section titled “XML через sXML”Бібліотека Serial XML — потокова обробка. Підтримує XML 1.0, XOP, binary XML, JSON. Без DOM — тому швидше й менше пам’яті. Два стилі: token-based (низькорівневий) та object-oriented (обгортка).
Рендеринг (token-based):
DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 encoding = 'UTF-8' ) ).
TRY. writer->open_element( name = 'flights' ). writer->open_element( name = 'flight' ). writer->open_element( name = 'carrier' ). writer->write_value( 'LH' ). writer->close_element( ). writer->open_element( name = 'number' ). writer->write_value( '400' ). writer->close_element( ). writer->close_element( ). writer->close_element( ). CATCH cx_sxml_state_error.ENDTRY.
DATA(xml) = CAST cl_sxml_string_writer( writer )->get_output( ). " xstringПарсинг (token-based):
DATA(reader) = cl_sxml_string_reader=>create( xml_bin ).
TRY. DO. reader->next_node( ). IF reader->node_type = if_sxml_node=>co_nt_final. EXIT. ENDIF.
CASE reader->node_type. WHEN if_sxml_node=>co_nt_element_open. " reader->name; ітерувати атрибути через next_attribute( ) WHEN if_sxml_node=>co_nt_value. " reader->value WHEN if_sxml_node=>co_nt_element_close. " ... ENDCASE. ENDDO. CATCH cx_sxml_state_error.ENDTRY.CALL TRANSFORMATION
Section titled “CALL TRANSFORMATION”Трансформації працюють через проміжний формат asXML (для XML) або asJSON (для JSON). Варіанти:
| Тип | Опис |
|---|---|
| XSLT | Репозиторний об’єкт із XSL-кодом. |
| Simple Transformation (ST) | SAP-специфічна мова для ABAP ↔ XML. |
Identity (ID) | Вбудована тотожна трансформація. Серіалізує ABAP → asXML/asJSON і назад. |
Синтаксис
Section titled “Синтаксис”" Статичне ім'я трансформаціїCALL TRANSFORMATION zsome_xslt SOURCE ... RESULT ...
" Тотожна трансформація IDCALL TRANSFORMATION id SOURCE ... RESULT ...
" Динамічне ім'яTRY. CALL TRANSFORMATION ('ID') SOURCE ... RESULT ... CATCH cx_invalid_transformation.ENDTRY.Джерело (SOURCE)
Section titled “Джерело (SOURCE)”| Форма | Значення |
|---|---|
SOURCE XML src | src містить XML 1.0 (string, xstring, таблиця, sXML/iXML reader) |
SOURCE JSON src | JSON-дані |
SOURCE name1 = abap1 name2 = abap2 | ABAP-об’єкти; nameN — ім’я XML-елемента |
SOURCE (srctab) | Динамічно, srctab типу abap_trans_srcbind_tab |
Результат (RESULT)
Section titled “Результат (RESULT)”| Форма | Значення |
|---|---|
RESULT XML res | XML у string/xstring/table/sXML writer/iXML ostream |
RESULT JSON res | JSON |
RESULT name1 = abap1 ... | ABAP-об’єкти |
RESULT (restab) | Динамічно, abap_trans_resbind_tab |
Приклади з ID
Section titled “Приклади з ID”TYPES: BEGIN OF line, char TYPE c LENGTH 3, int TYPE i, END OF line.DATA(tab) = VALUE TABLE OF line WITH EMPTY KEY( ( char = 'aaa' int = 1 ) ( char = 'bbb' int = 2 ) ).
" ABAP → asXML (xstring)CALL TRANSFORMATION id SOURCE itab = tab RESULT XML DATA(xml_out).
" XML → ABAPDATA tab_back LIKE tab.CALL TRANSFORMATION id SOURCE XML xml_out RESULT itab = tab_back.
" OPTIONS для прибрання XML-заголовкаTYPES c50_tab TYPE TABLE OF c LENGTH 50 WITH EMPTY KEY.DATA chartab TYPE c50_tab.CALL TRANSFORMATION id SOURCE itab = tab RESULT XML chartab OPTIONS xml_header = 'NO'.JSON — огляд варіантів
Section titled “JSON — огляд варіантів”sXML: тим самим API, що й XML
Section titled “sXML: тим самим API, що й XML”Той же cl_sxml_string_writer/reader, але з типом if_sxml=>co_xt_json. Всередині ABAP обробляє JSON через проміжний формат JSON-XML.
DATA(json_writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ) ).
json_writer->open_element( name = 'object' ). json_writer->open_element( name = 'str' ). json_writer->write_attribute( name = 'name' value = 'carrier_id' ). json_writer->write_value( value = 'LH' ). json_writer->close_element( ).json_writer->close_element( ).
DATA(json) = cl_abap_conv_codepage=>create_in( )->convert( CAST cl_sxml_string_writer( json_writer )->get_output( ) )." {"carrier_id":"LH"}CALL TRANSFORMATION із JSON
Section titled “CALL TRANSFORMATION із JSON”" ABAP → JSONDATA(writer) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).CALL TRANSFORMATION id SOURCE hi = `Hello` RESULT XML writer.DATA(json) = cl_abap_conv_codepage=>create_in( )->convert( writer->get_output( ) )." {"HI":"Hello"}
" JSON → ABAP через RESULT JSON / SOURCE JSONDATA num TYPE i VALUE 123.CALL TRANSFORMATION id SOURCE var = num RESULT JSON DATA(json_out).
DATA int TYPE i.CALL TRANSFORMATION id SOURCE JSON json_out RESULT var = int.Pretty-print — через опції writer’а:
DATA(w) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ) ).w->set_option( option = if_sxml_writer=>co_opt_linebreaks ).w->set_option( option = if_sxml_writer=>co_opt_indent ).
CALL TRANSFORMATION id SOURCE itab = it RESULT XML w.XCO (Cloud ABAP)
Section titled “XCO (Cloud ABAP)”Найчистіший варіант для типових задач JSON.
DATA: BEGIN OF carrier, carrier_id TYPE c LENGTH 3, connection_id TYPE n LENGTH 4, city_from TYPE c LENGTH 20, city_to TYPE c LENGTH 20, END OF carrier.
carrier = VALUE #( carrier_id = 'AA' connection_id = '17' city_from = 'New York' city_to = 'San Francisco' ).
" ABAP → JSONDATA(json) = xco_cp_json=>data->from_abap( carrier )->to_string( ).
" JSON → ABAPDATA back LIKE carrier.xco_cp_json=>data->from_string( json )->write_to( REF #( back ) ).
" Побудова вручну через builderDATA(b) = xco_cp_json=>data->builder( ).b->begin_object( )->add_member( 'CarrierId' )->add_string( 'DL' )->add_member( 'ConnectionId' )->add_string( '1984' )->end_object( ).DATA(result_json) = b->get_data( )->to_string( ).
" Name-конвенції (camelCase JSON → ABAP underscore)xco_cp_json=>data->from_string( result_json )->apply( VALUE #( ( xco_cp_json=>transformation->pascal_case_to_underscore ) ) )->write_to( REF #( back ) )./ui2/cl_json (класичний ABAP)
Section titled “/ui2/cl_json (класичний ABAP)”DATA(tab) = VALUE string_table( ( `aaa` ) ( `bbb` ) ).
" Серіалізація з опціямиDATA(json) = /ui2/cl_json=>serialize( data = tab ).DATA(json_pretty) = /ui2/cl_json=>serialize( data = tab format_output = abap_true pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
" ДесеріалізаціяDATA back TYPE string_table./ui2/cl_json=>deserialize( EXPORTING json = json CHANGING data = back ).
" З name mapping (різні імена полів у JSON і ABAP)/ui2/cl_json=>deserialize( EXPORTING json = some_json name_mappings = VALUE #( ( abap = 'CARR' json = `CARRIER_ID` ) ( abap = 'CONN' json = `CONNECTION_ID` ) ) CHANGING data = target ).
" Невідомий тип — згенерувати динамічноDATA(dref) = /ui2/cl_json=>generate( json = some_json ). " ref to dataСеріалізація об’єктів
Section titled “Серіалізація об’єктів”Об’єкти (instance класу) можна серіалізувати через CALL TRANSFORMATION id, якщо клас реалізує інтерфейс IF_SERIALIZABLE_OBJECT.
CLASS zcl_demo DEFINITION. PUBLIC SECTION. INTERFACES if_serializable_object. PRIVATE SECTION. DATA timestamp TYPE utclong. DATA n TYPE i.ENDCLASS.
" СеріалізуватиDATA(obj) = NEW zcl_demo( ).obj->timestamp = utclong_current( ).obj->n = 42.
DATA serialized TYPE string.CALL TRANSFORMATION id SOURCE obj = obj RESULT XML serialized.
" ДесеріалізуватиDATA deserialized TYPE REF TO zcl_demo.CALL TRANSFORMATION id SOURCE XML serialized RESULT obj = deserialized.Налаштування через SERIALIZE_HELPER / DESERIALIZE_HELPER: приватні instance-методи однакової сигнатури. Дозволяють виключити окремі атрибути з серіалізації. Обидва реалізуються або жодного.
Допоміжні перетворення
Section titled “Допоміжні перетворення”string ↔ xstring
Section titled “string ↔ xstring”" string → xstring (UTF-8 за замовчуванням)DATA(bin) = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( `<TXT>ABAP</TXT>` ).
" xstring → stringDATA(str) = cl_abap_conv_codepage=>create_in( )->convert( bin ).
" Через XCODATA(bin2) = xco_cp=>string( `<TXT>ABAP</TXT>` )->as_xstring( xco_cp_character=>code_page->utf_8 )->value.DATA(str2) = xco_cp=>xstring( bin2 )->as_string( xco_cp_character=>code_page->utf_8 )->value.Стиснення (gzip)
Section titled “Стиснення (gzip)”DATA comp TYPE xstring.DATA decomp TYPE xstring.
TRY. cl_abap_gzip=>compress_binary( EXPORTING raw_in = raw_bin IMPORTING gzip_out = comp ). cl_abap_gzip=>decompress_binary( EXPORTING gzip_in = comp IMPORTING raw_out = decomp ). CATCH cx_parameter_invalid_range cx_sy_buffer_overflow cx_sy_compression_error.ENDTRY.EXPORT / IMPORT (data clusters)
Section titled “EXPORT / IMPORT (data clusters)”Швидка бінарна серіалізація кількох об’єктів у xstring.
DATA buffer TYPE xstring.
" Запис (з компресією)EXPORT flights = itab1 TO DATA BUFFER buffer COMPRESSION ON.
" ЧитанняDATA itab2 LIKE itab1.IMPORT flights = itab2 FROM DATA BUFFER buffer.
" Кілька об'єктів одразуEXPORT int1 = 100 int2 = 200 TO DATA BUFFER buffer.IMPORT int1 = num1 int2 = num2 FROM DATA BUFFER buffer.Коли використовувати що
Section titled “Коли використовувати що”| Задача | Рішення |
|---|---|
| Навігація великим XML з DTD | iXML |
| Потоковий парсинг XML/JSON | sXML |
| ABAP-структура → XML/JSON і назад (типовий випадок) | CALL TRANSFORMATION id + XCO |
| XML з нестандартним форматом | XSLT або Simple Transformation |
| Швидке JSON ↔ ABAP у Cloud | xco_cp_json |
| JSON з name mapping | /ui2/cl_json |
| Серіалізація інстансу класу | IF_SERIALIZABLE_OBJECT + CALL TRANSFORMATION id |
| Пакування кількох об’єктів у xstring | EXPORT/IMPORT ... TO/FROM DATA BUFFER |
| Стиснути бінарні дані | cl_abap_gzip |
| string ↔ xstring | cl_abap_conv_codepage або XCO |
Адаптовано з 21_XML_JSON.md (Apache 2.0).