odata 服务通用调用RFC函数模块

本文档介绍了如何在SE11中创建结构,并基于这些结构建立OData服务。通过重定义/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_ENTITY方法,实现通用的OData服务调用ABAP RFC函数。使用/IWFND/MAINT_SERVICE工具测试服务,通过POST方法发送JSON数据,调用服务并传递参数。这种方法适用于减少创建多个类似OData服务的需求,只需一个通用服务即可动态调用不同的ABAP函数模块。
摘要由CSDN通过智能技术生成

SE11新建结构

IKEYNA    1 Types    /SCMTMS/STRING    STRING    0    0    0    String
IVALUE    1 Types    /SCMTMS/STRING    STRING    0    0    0    String
ZOUTPUT    1 Types    /SCMTMS/STRING    STRING    0    0    0    String

Odata 引用上面结构创建ODATA 服务

重定义

/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_ENTITY

方法

CREATE_ENTITY 代码:

 DATA:ls_data TYPE  zcl_ztest_fiori_01_mpc_ext=>ts_zfiori_web.
    IF iv_entity_set_name = 'ZFIORI_WEBSet'.
*Transform INPUT REQUEST FROM ODATA-SERVICE into the internal structure
      io_data_provider->read_entry_data(
      IMPORTING
       es_data = ls_data ).

      DATA lt_params  TYPE TABLE OF rfc_fint_p.

      DATA(lv_funcname) = ls_data-ikeyna."函数名

      DATA:lv_str_json TYPE string.

      lv_str_json = ls_data-ivalue.


      zcl_json_handler=>build_params(
        EXPORTING
          function_name          = CONV #( lv_funcname )
        IMPORTING
          paramtab               = DATA(lt_paramtab)
          exceptab               = DATA(lt_exceptab)
          params                 = lt_params
        EXCEPTIONS
          invalid_function       = 1
          unsupported_param_type = 2
             ).
      IF sy-subrc <> 0.
* Implement suitable error handling here
      ENDIF.

      DATA: lo_oexcp        TYPE REF TO cx_root.
      TRY.
          CALL METHOD zcl_json_handler=>json_deserialize
            EXPORTING
              json     = lv_str_json
            CHANGING
              paramtab = lt_paramtab.
          TRY.
              CALL FUNCTION lv_funcname
                PARAMETER-TABLE lt_paramtab
                EXCEPTION-TABLE lt_exceptab.
            CATCH cx_root INTO lo_oexcp.
              DATA(lv_etext) = lo_oexcp->if_message~get_longtext(  preserve_newlines = abap_true ).
              MESSAGE lv_etext TYPE 'E'.

          ENDTRY.
        CATCH cx_root INTO lo_oexcp.
          lv_etext = lo_oexcp->if_message~get_text( ).
          MESSAGE lv_etext TYPE 'E'.
      ENDTRY.

      zcl_json_handler=>serialize_json(
        EXPORTING
          paramtab  = lt_paramtab
          params    = lt_params
        IMPORTING
          o_string  = DATA(o_string)
             ).
      ls_data-zoutput =  o_string.

      copy_data_to_ref(
      EXPORTING
       is_data = ls_data
      CHANGING
       cr_data = er_entity
      ).
    ENDIF.

用的工具类代码:

class ZCL_JSON_HANDLER definition
  public
  create public .

public section.
  type-pools ABAP .
  type-pools JS .

*"* public components of class ZCL_JSON_HANDLER
*"* do not include other source files here!!!
  interfaces IF_HTTP_EXTENSION .

  constants XNL type ABAP_CHAR1 value %_NEWLINE ##NO_TEXT.
  constants XCRLF type ABAP_CR_LF value %_CR_LF ##NO_TEXT.
  data MY_SERVICE type STRING .
  data MY_URL type STRING .

  class-methods ABAP2JSON
    importing
      !ABAP_DATA type DATA
      !NAME type STRING optional
      !UPCASE type XFELD optional
      !CAMELCASE type XFELD optional
      !CAMELCASE_NAMES type STRINGTAB optional
    returning
      value(JSON_STRING) type STRING
    exceptions
      ERROR_IN_DATA_DESCRIPTION .
  class-methods ABAP2PERL
    importing
      !ABAP_DATA type DATA
      !NAME type STRING optional
      !UPCASE type XFELD optional
    returning
      value(PERL_STRING) type STRING
    exceptions
      ERROR_IN_DATA_DESCRIPTION .
  class-methods ABAP2XML
    importing
      !ABAP_DATA type DATA
      !NAME type STRING optional
      !WITH_XML_HEADER type ABAP_BOOL default ABAP_FALSE
      !UPCASE type XFELD optional
      !NAME_ATR type STRING optional
    returning
      value(XML_STRING) type STRING .
  class-methods ABAP2YAML
    importing
      !ABAP_DATA type DATA
      !NAME type STRING optional
      !UPCASE type XFELD optional
      !Y_LEVEL type I default 0
      !S_INDEX type I default 0
      !FIRST_ROW type XFELD optional
      !DONT_INDENT type XFELD optional
    returning
      value(YAML_STRING) type STRING
    exceptions
      ERROR_IN_DATA_DESCRIPTION .
  class-methods BUILD_PARAMS
    importing
      !FUNCTION_NAME type RS38L_FNAM
    exporting
      !PARAMTAB type ABAP_FUNC_PARMBIND_TAB
      !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB
      !PARAMS type ANY
    exceptions
      INVALID_FUNCTION
      UNSUPPORTED_PARAM_TYPE .
  class-methods JSON2ABAP
    importing
      !JSON_STRING type STRING optional
      !VAR_NAME type STRING optional
      !PROPERTY_PATH type STRING default 'json_obj'
    exporting
      value(PROPERTY_TABLE) type JS_PROPERTY_TAB
    changing
      !JS_OBJECT type ref to CL_JAVA_SCRIPT optional
      value(ABAP_DATA) type ANY optional
    raising
      ZCX_JSON .
  class-methods JSON_DESERIALIZE
    importing
      !JSON type STRING
    changing
      !PARAMTAB type ABAP_FUNC_PARMBIND_TAB
    raising
      ZCX_JSON .
  methods NOTES
    returning
      value(TEXT) type STRING .
  class-methods SERIALIZE_JSON
    importing
      !PARAMTAB type ABAP_FUNC_PARMBIND_TAB
      !PARAMS type ANY optional
      !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional
      !SHOW_IMPP type ABAP_BOOL optional
      !JSONP type STRING optional
      !LOWERCASE type ABAP_BOOL default ABAP_TRUE
      !CAMELCASE type ABAP_BOOL default ABAP_FALSE
      !CAMELCASE_NAMES type STRINGTAB optional
    exporting
      !O_STRING type STRING .
  class-methods SERIALIZE_PERL
    importing
      !PARAMTAB type ABAP_FUNC_PARMBIND_TAB
      !PARAMS type ANY optional
      !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional
      !SHOW_IMPP type ABAP_BOOL optional
      !JSONP type STRING optional
      !LOWERCASE type ABAP_BOOL default ABAP_FALSE
      !FUNCNAME type RS38L_FNAM
    exporting
      !PERL_STRING type STRING .
  class-methods SERIALIZE_XML
    importing
      !PARAMTAB type ABAP_FUNC_PARMBIND_TAB
      !PARAMS type ANY optional
      !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional
      !SHOW_IMPP type ABAP_BOOL optional
      !JSONP type STRING optional
      !FUNCNAME type RS38L_FNAM
      !LOWERCASE type ABAP_BOOL default ABAP_FALSE
      !FORMAT type STRING optional
    exporting
      !O_STRING type STRING .
  class-methods SERIALIZE_YAML
    importing
      !PARAMTAB type ABAP_FUNC_PARMBIND_TAB
      !PARAMS type ANY optional
      !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional
      !SHOW_IMPP type ABAP_BOOL optional
      !JSONP type STRING optional
      !LOWERCASE type ABAP_BOOL default ABAP_FALSE
    exporting
      !YAML_STRING type STRING .
  class-methods DESERIALIZE_ID
    importing
      !JSON type STRING
    changing
      !PARAMTAB type ABAP_FUNC_PARMBIND_TAB
    raising
      ZCX_JSON .
  class-methods SERIALIZE_ID
    importing
      !PARAMTAB type ABAP_FUNC_PARMBIND_TAB
      !PARAMS type ANY optional
      !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional
      !SHOW_IMPP type ABAP_BOOL optional
      !JSONP type STRING optional
      !LOWERCASE type ABAP_BOOL default ABAP_FALSE
      !FORMAT type STRING default 'JSON'
      !FUNCNAME type RS38L_FNAM optional
      !CAMELCASE type ABAP_BOOL default ABAP_FALSE
    exporting
      !O_STRING type STRING
    raising
      ZCX_JSON .
protected section.
*"* protected components of class ZCL_JSON_HANDLER
*"* do not include other source files here!!!
private section.
*"* private components of class ZCL_JSON_HANDLER
*"* do not include other source files here!!!
ENDCLASS.



CLASS ZCL_JSON_HANDLER IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>ABAP2JSON
* +-------------------------------------------------------------------------------------------------+
* | [--->] ABAP_DATA                      TYPE        DATA
* | [--->] NAME                           TYPE        STRING(optional)
* | [--->] UPCASE                         TYPE        XFELD(optional)
* | [--->] CAMELCASE                      TYPE        XFELD(optional)
* | [--->] CAMELCASE_NAMES                TYPE        STRINGTAB(optional)
* | [<-()] JSON_STRING                    TYPE        STRING
* | [EXC!] ERROR_IN_DATA_DESCRIPTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
method abap2json.
*/**********************************************/*
*/ This method takes any ABAP data variable and /*
*/ returns a string representing its value in   /*
*/ JSON format.                                 /*
*/ ABAP references are always de-referenced and /*
*/ treated as normal variables.                 /*
*/**********************************************/*

  type-pools: abap.

  constants:
    c_comma type c value ',',
    c_colon type c value ':',
    c_quote type c value '"'.

  data:
    dont_quote      type xfeld,
    json_fragments  type table of string,
    rec_json_string type string,
    l_type          type c,
    s_type          type c,
    l_comps         type i,
    l_lines         type i,
    l_index         type i,
    l_value         type string,
    l_name          type string,
    l_strudescr     type ref to cl_abap_structdescr.

  field-symbols:
    <abap_data> type any,
    <itab>      type any table,
    <stru>      type any table,
    <comp>      type any,
    <abapcomp>  type abap_compdescr.

  data   my_camelcase    type xfeld.
  my_camelcase = camelcase.

  define get_scalar_value.
    " &1 : assigned var
    " &2 : abap data
    " &3 : abap type
    &1 = &2.
****************************************************
* Adapt some basic ABAP types (pending inclusion of all basic abap types?)
* Feel free to customize this for your needs
    case &3.
*       1. ABAP numeric types
      when 'I'. " Integer
        condense &1.
        if sign( &1 ) < 0.
          shift &1 by 1 places right circular.
        endif.
        dont_quote = 'X'.

      when 'F'. " Float
        condense &1.
        dont_quote = 'X'.

      when 'P'. " Packed number (used in quantities or currency, for example)
        condense &1.
        if sign( &1 ) < 0.
          shift &1 by 1 places right circular.
        endif.
        dont_quote = 'X'.

      when 'X'. " Hexadecimal
        condense &1.
        concatenate '0x' &1 into &1.
*        dont_quote = 'X'.
*        "Quote it, as JSON doesn't support Hex or Octal as native types.

*       2. ABAP char types
      when 'D'. " Date type
        CONCATENATE &1(4) '-' &1+4(2) '-' &1+6(2) INTO &1.

      when 'T'. " Time representation
        CONCATENATE &1(2) ':' &1+2(2) ':' &1+4(2) INTO &1.

      when 'N'. " Numeric text field
*           condense &1.

      when 'C' or 'g'. " Char sequences and Strings
* Put safe chars
        replace all occurrences of '\' in &1 with '\\' .
        replace all occurrences of '"' in &1 with '\"' .
        replace all occurrences of cl_abap_char_utilities=>cr_lf in &1 with '\r\n' .
        replace all occurrences of cl_abap_char_utilities=>newline in &1 with '\n' .
        replace all occurrences of cl_abap_char_utilities=>horizontal_tab in &1 with '\t' .
        replace all occurrences of cl_abap_char_utilities=>backspace in &1 with '\b' .
        replace all occurrences of cl_abap_char_utilities=>form_feed in &1 with '\f' .

      when 'y'.  " XSTRING
* Put the XSTRING in Base64
        &1 = cl_http_utility=>ENCODE_X_BASE64( &2 ).

      when others.
* Don't hesitate to add and modify scalar abap types to suit your taste.

    endcase.
** End of scalar data preparing.

* Enclose value in quotes (or not)
    if dont_quote ne 'X'.
      concatenate c_quote &1 c_quote into &1.
    endif.

    clear dont_quote.

  end-of-definition.


***************************************************
*  Prepare field names, JSON does quote names!!   *
*  You must be strict in what you produce.        *
***************************************************
  if name is not initial.
    concatenate c_quote name c_quote c_colon into rec_json_string.
    append rec_json_string to json_fragments.
    clear rec_json_string.
  endif.

**
* Get ABAP data type
  describe field abap_data type l_type components l_comps.

***************************************************
*  Get rid of data references
***************************************************
  if l_type eq cl_abap_typedescr=>typekind_dref.
    assign abap_data->* to <abap_data>.
    if sy-subrc ne 0.
      append '{}' to json_fragments.
      concatenate lines of json_fragments into json_string.
      exit.
    endif.
  else.
    assign abap_data to <abap_data>.
  endif.

* Get ABAP data type again and start
  describe field <abap_data> type l_type components l_comps.

***************************************************
*  Tables
***************************************************
  if l_type eq cl_abap_typedescr=>typekind_table.
* '[' JSON table opening bracket
    append '[' to json_fragments.
    assign <abap_data> to <itab>.
    l_lines = lines( <itab> ).
    loop at <itab> assigning <comp>.
      add 1 to l_index.
*> Recursive call for each table row:
      rec_json_string = abap2json( abap_data = <comp> upcase = upcase camelcase = my_camelcase camelcase_names = camelcase_names ).
      append rec_json_string to json_fragments.
      clear rec_json_string.
      if l_index < l_lines.
        append c_comma to json_fragments.
      endif.
    endloop.
    append ']' to json_fragments.
* ']' JSON table closing bracket


***************************************************
*  Structures
***************************************************
  else.
    if l_comps is not initial.
* '{' JSON object opening curly brace
      append '{' to json_fragments.
      l_strudescr ?= cl_abap_typedescr=>describe_by_data( <abap_data> ).
      loop at l_strudescr->components assigning <abapcomp>.
        l_index = sy-tabix .
        assign component <abapcomp>-name of structure <abap_data> to <comp>.
        l_name = <abapcomp>-name.
** ABAP names are usually in caps, set upcase to avoid the conversion to lower case.
        if upcase ne 'X'.
          " translate l_name to lower case.
          l_name = to_lower( l_name ).
        endif.
        if camelcase eq 'X'.
          l_name = to_mixed( val = l_name  case = 'a' ).
        else.
          read table camelcase_names from l_name transporting no fields.
          if sy-subrc eq 0.
            l_name = to_mixed( val = l_name  case = 'a' ).
            my_camelcase = 'X'.
          else.
            my_camelcase = abap_false.
          endif.
        endif.
        describe field <comp> type s_type.
        if s_type eq cl_abap_typedescr=>typekind_table or s_type eq cl_abap_typedescr=>typekind_dref or
           s_type eq cl_abap_typedescr=>typekind_struct1 or s_type eq cl_abap_typedescr=>typekind_struct2.
*> Recursive call for non-scalars:
          rec_json_string = abap2json( abap_data = <comp> name = l_name upcase = upcase camelcase = my_camelcase camelcase_names = camelcase_names ).
        else.
          if s_type eq cl_abap_typedescr=>typekind_oref or s_type eq cl_abap_typedescr=>typekind_iref.
            rec_json_string = '"REF UNSUPPORTED"'.
          else.
            get_scalar_value rec_json_string <comp> s_type.
          endif.
          concatenate c_quote l_name c_quote c_colon rec_json_string into rec_json_string.
        endif.
        append rec_json_string to json_fragments.
        clear rec_json_string. clear l_name.
        if l_index < l_comps.
          append c_comma to json_fragments.
        endif.
      endloop.
      append '}' to json_fragments.
* '}' JSON object closing curly brace


****************************************************
*                  - Scalars -                     *
****************************************************
    else.
      get_scalar_value l_value <abap_data> l_type.
      append l_value to json_fragments.

    endif.
* End of structure/scalar IF block.
***********************************

  endif.
* End of main IF block.
**********************

* Use a loop in older releases that don't support concatenate lines.
  concatenate lines of json_fragments into json_string.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>ABAP2PERL
* +-------------------------------------------------------------------------------------------------+
* | [--->] ABAP_DATA                      TYPE        DATA
* | [--->] NAME                           TYPE        STRING(optional)
* | [--->] UPCASE                         TYPE        XFELD(optional)
* | [<-()] PERL_STRING                    TYPE        STRING
* | [EXC!] ERROR_IN_DATA_DESCRIPTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ABAP2PERL.
*/**********************************************/*
*/ This method takes any ABAP data variable and /*
*/ returns a string representing its value in   /*
*/ Perl Data::Dumper format, ready to be evaled /*
*/ in a Perl program.                           /*
*/**********************************************/*

  type-pools: abap.

  constants:
    c_comma type c value ',',
    c_colon type c value ':',
    c_quote type c value ''''.

  data:
    perl_hash_assign type string,
    dont_quote type xfeld,
    perl_fragments type table of string,
    rec_perl_string type string,
    l_type  type c,
    s_type  type c,
    l_comps type i,
    l_lines type i,
    l_index type i,
    l_value type string,
    l_name  type string,
    l_typedescr type ref to cl_abap_structdescr.

  field-symbols:
    <abap_data> type any,
    <itab> type any table,
    <stru> type any table,
    <comp> type any,
    <abapcomp> type abap_compdescr.

  concatenate space '=>' space into perl_hash_assign respecting blanks.

  define get_scalar_value.
    " &1 : assigned var
    " &2 : abap data
    " &3 : abap type
    &1 = &2.
****************************************************
* Adapt some basic ABAP types (pending inclusion of all basic abap types?)
* Feel free to customize this for your needs
    case &3.
*       1. ABAP numeric types
      when 'I'. " Integer
        condense &1.
        if sign( &1 ) < 0.
          shift &1 by 1 places right circular.
        endif.
        dont_quote = 'X'.

      when 'F'. " Float
        condense &1.
        dont_quote = 'X'.

      when 'P'. " Packed number (used in quantities, for example)
        condense &1.
        if sign( &1 ) < 0.
          shift &1 by 1 places right circular.
        endif.
        dont_quote = 'X'.

      when 'X'. " Hexadecimal
        condense &1.
        concatenate '0x' &1 into &1.
        dont_quote = 'X'.

*       2. ABAP char types
      when 'D'. " Date type
        CONCATENATE &1(4) '-' &1+4(2) '-' &1+6(2) INTO &1.

      when 'T'. " Time representation
        CONCATENATE &1(2) ':' &1+2(2) ':' &1+4(2) INTO &1.

      when 'N'. " Numeric te
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值