Преобразование данных ABAP в объект iXML, представляющий их в формате JSON-XML - PullRequest
2 голосов
/ 24 апреля 2019

Я хочу прочитать произвольные данные ABAP в объект документа iXML, который содержит представление JSON-XML этих данных.

Единственный способ, которым я вижу, - двойное применение преобразования id, которое не очень эффективно:

data(lo_aux1) = cl_sxml_string_writer=>create( if_sxml=>co_xt_json ).
call transformation id
  source data = ls_some_abap_data
  result xml lo_aux1.
data(lv_aux2) = lo_aux1->get_output( ).
data(lo_result) = cl_ixml=>create( )->create_document( ).
call transformation id
  source xml lv_aux2
  result xml lo_result. 

Теперь lo_result является представлением iXML DOM данных ABAP в формате JSON-XML, как требуется. Можно ли получить его более прямым способом?

Примечание: меня не интересуют объекты результатов семейства sXML , так как я хочу манипулировать / расширять результирующий документ JSON-XML обычными методами XML DOM, что невозможно для sXML объект записи (sXML записи настолько просты, что могут записывать только все, что у них есть, в выходной объект, но не позволяют редактировать части объекта, которые они уже содержат).

1 Ответ

1 голос
/ 03 июля 2019

Я сижу у прокси и хочу обогатить входящую полезную нагрузку JSON некоторыми данными ABAP, прежде чем передать ее в конечную точку. Стратегия: проанализируйте входящий JSON в документе JSON-XML, прочитайте (сложные) данные ABAP во второй документ XML, затем добавьте поддеревья XML второго к первому, прежде чем, наконец, получить результат JSON из первого документа JSON-XML

Я вообще не понимаю, нужен ли здесь iXML. Преобразование сложной структуры ABAP в XML для ее слияния с JSON здесь является излишним. Предположим, вы получили некоторые данные JSON от Web-сервиса:

{  
   "main":{  
      "PASSENGERS":[  
         {  
            "NAME":"Horst",
            "TITLE":"Herr",
            "AGE":30
         },
         {  
            "NAME":"Jutta",
            "TITLE":"Frau",
            "AGE":35
         },
         {  
            "NAME":"Ingo",
            "TITLE":"Herr",
            "AGE":31
         }
      ]
   }
}

И вы хотите дополнить данные каждого пассажира данными рейса из таблицы SFLIGHT. Вы можете манипулировать узлами и атрибутами с помощью cl_sxml_string_writer, например:

DATA(lv_json) = CONV string( '{"main": {"PASSENGERS":[ {"NAME":"Horst","TITLE":"Herr","AGE":30}, {"NAME":"Jutta","TITLE":"Frau","AGE":35}, {"NAME":"Ingo","TITLE":"Herr","AGE":31} ]}}' ).

DATA open_element TYPE REF TO if_sxml_open_element.
DATA value TYPE REF TO if_sxml_value_node.

DATA(o_json) = cl_abap_codepage=>convert_to( lv_json ).
DATA(reader) = cl_sxml_string_reader=>create( o_json ).

SELECT DISTINCT connid, fldate, planetype FROM sflight INTO TABLE @DATA(lt_flight).

DATA(xml) = cl_abap_codepage=>convert_to( lv_json ).

DATA(out) = cl_demo_output=>new( )->begin_section( 'Original JSON' )->write_xml( xml ).

DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( ) ).
open_element = writer->new_open_element( name = 'flights' nsuri = reader->nsuri ).
writer->write_node( open_element ).
DATA(i) = 1.
DO.
  DATA(node) = reader->read_next_node( ).
  IF node IS INITIAL.
    EXIT.
  ENDIF.
  IF node IS INSTANCE OF if_sxml_value_node.
    DATA(value_node) = CAST if_sxml_value_node( node ).
    value_node->set_value( to_upper( value_node->get_value( ) ) ).
  ENDIF.
  writer->write_node( node ).
  IF node->type = if_sxml_node=>co_nt_element_open.
    DATA(op) = CAST if_sxml_open_element( node ).
    CHECK op->qname-name = 'object' AND op->get_attributes( ) IS INITIAL.
    open_element = writer->new_open_element( name = 'flight' nsuri = reader->nsuri ).
    open_element->set_attribute( name = 'FLIGHT_DATE'
                                 value = | { lt_flight[ i ]-fldate } | ).
    open_element->set_attribute( name = 'PLANE_TYPE'
                                 value = | { lt_flight[ i ]-planetype } | ).
    writer->write_node( open_element ).
    value = writer->new_value( ).
    value->set_value( | { lt_flight[ i ]-connid } | ).
    writer->write_node( value ).
    writer->write_node( writer->new_close_element( ) ).
    i = i + 1.
  ENDIF.
ENDDO.
writer->write_node( writer->new_close_element( ) ).
out->next_section( 'Modified JSON'
  )->write_xml(
    CAST cl_sxml_string_writer( writer )->get_output( )
  )->display( ).

DATA(result_json) = CAST cl_sxml_string_writer( writer )->get_output(  ).

Полученный JSON будет выгружен в переменную result_json, и вы можете перемещать его дальше, куда хотите.

Здесь приведен JSON с заглавными буквами для пассажиров и расширен с узлом flight, который содержит номер рейса и связан с данными и типом самолета:

<flights>
 <object>
  <flight FLIGHT_DATE=" 20160610 " PLANE_TYPE=" A380‑800 "> 0002 </flight>
  <object name="main">
   <array name="PASSENGERS">
    <object>
     <flight FLIGHT_DATE=" 20160712 " PLANE_TYPE=" A380‑800 "> 0002 </flight>
     <str name="NAME">HORST</str>
     <str name="TITLE">HERR</str>
     <num name="AGE">30</num>
    </object>
    <object>
     <flight FLIGHT_DATE=" 20160813 " PLANE_TYPE=" A380‑800 "> 0002 </flight>
     <str name="NAME">JUTTA</str>
     <str name="TITLE">FRAU</str>
     <num name="AGE">35</num>
    </object>
    <object>
     <flight FLIGHT_DATE=" 20160914 " PLANE_TYPE=" A380‑800 "> 0002 </flight>
     <str name="NAME">INGO</str>
     <str name="TITLE">HERR</str>
     <num name="AGE">31</num>
    </object>
   </array>
  </object>
 </object>
</flights> 
...