
这里封装了一个类,可以解析任何json,然后根据抬头传入的函数ID找对应的函数模块,动态调用函数模块,使用到了动态结构和动态编程和动态调用函数
文章目录
- 创建函数模块
- 创建服务
- 激活服务
- 测试服务
- 创建消息类型结构
- 创建URL配置表
- 维护配置表的内容
- 维护功能模块参数表
- 创建动态结构
- 调用函数
- 类ZCL_SCARR_0001类
- 函数模块ZFC_SCARR_1
- Postman调试
创建函数模块

创建结构

导入参数

导出参数

创建类

创建服务

激活服务

测试服务

创建消息类型结构

当前核心代码

js
METHOD IF_HTTP_EXTENSION~HANDLE_REQUEST.
DATA : LV_METHOD TYPE STRING."HTTP 方法
DATA : LT_FIELDS TYPE TIHTTPNVP,
LS_FIELDS TYPE IHTTPNVP.
TYPES:BEGIN OF GTY_HEADER_FIELDS,
SNDPRN TYPE STRING,
ZRFCID TYPE STRING,
END OF GTY_HEADER_FIELDS.
DATA LS_HEADER_FIELDS TYPE GTY_HEADER_FIELDS.
DATA LS_RESPONSE TYPE ZSAPPO_RET_INFO.
DATA LS_JSON TYPE STRING.
LV_METHOD = SERVER->REQUEST->GET_HEADER_FIELD( NAME = '~request_method' ).
SERVER->REQUEST->GET_HEADER_FIELDS( CHANGING FIELDS = LT_FIELDS ).
"---解析url 参数 ~query_string
READ TABLE LT_FIELDS INTO LS_FIELDS WITH KEY NAME = '~query_string'.
IF SY-SUBRC = 0.
SPLIT LS_FIELDS-VALUE AT '&' INTO TABLE DATA(LT_QUERY_STRING).
LOOP AT LT_QUERY_STRING INTO DATA(LS_QUERY_STRING).
IF LS_QUERY_STRING CS 'sndprn' OR LS_QUERY_STRING CS 'zrfcid'.
CLEAR : LS_FIELDS.
SPLIT LS_QUERY_STRING AT '=' INTO LS_FIELDS-NAME LS_FIELDS-VALUE.
APPEND LS_FIELDS TO LT_FIELDS.
ENDIF.
ENDLOOP.
ENDIF.
LOOP AT LT_FIELDS INTO LS_FIELDS.
ASSIGN COMPONENT LS_FIELDS-NAME OF STRUCTURE LS_HEADER_FIELDS TO FIELD-SYMBOL(<FS_FIELD>).
IF <FS_FIELD> IS ASSIGNED.
<FS_FIELD> = LS_FIELDS-VALUE.
ENDIF.
UNASSIGN <FS_FIELD>.
ENDLOOP.
IF LS_HEADER_FIELDS-SNDPRN IS INITIAL.
LS_RESPONSE-CODE = 'E'.
LS_RESPONSE-MSG = 'SNDPRN不能为空!'.
ENDIF.
CALL METHOD ME->_RESPONSE_JSON
EXPORTING
SERVER = SERVER
IV_RESP = LS_RESPONSE
IMPORTING
EV_JSON = LS_JSON.
ENDMETHOD.

js
METHOD _RESPONSE_JSON.
DATA : LV_JSON TYPE STRING.
DATA : LS_RESPONSE TYPE ZSAPPO_RET_INFO.
IF IV_RESP IS NOT INITIAL.
"生成JSON
EV_JSON = /UI2/CL_JSON=>SERIALIZE( DATA = IV_RESP
PRETTY_NAME = /UI2/CL_JSON=>PRETTY_MODE-NONE ).
"---添加响应报文
SERVER->RESPONSE->IF_HTTP_ENTITY~SET_CONTENT_TYPE( CONTENT_TYPE = 'application/json' ).
SERVER->RESPONSE->SET_CDATA(
EXPORTING
DATA = EV_JSON " Character data
).
ENDIF.
ENDMETHOD.
创建URL配置表
维护配置表的内容

维护功能模块参数表

创建动态结构
传入结构的创建

传出结构的创建

调用函数
类ZCL_SCARR_0001类

方法

IF_HTTP_EXTENSION~HANDLE_REQUEST

js
METHOD IF_HTTP_EXTENSION~HANDLE_REQUEST.
DATA : LV_METHOD TYPE STRING."HTTP 方法
DATA : LT_FIELDS TYPE TIHTTPNVP,
LS_FIELDS TYPE IHTTPNVP.
TYPES:BEGIN OF GTY_HEADER_FIELDS,
REQKEYID TYPE STRING,
BUSINESSID TYPE STRING,
SNDPRN TYPE STRING,
ZRFCID TYPE STRING,
GET_REQUEST_JSON TYPE STRING,
TOKEN TYPE STRING,
END OF GTY_HEADER_FIELDS.
DATA LS_HEADER_FIELDS TYPE GTY_HEADER_FIELDS.
DATA LS_RESPONSE TYPE ZSAPPO_RET_INFO.
DATA LS_JSON TYPE STRING.
DATA: LR_REQ TYPE REF TO DATA,
LR_RET TYPE REF TO DATA.
DATA : LS_FUPARAREF TYPE FUPARAREF,
LT_FUPARAREF LIKE TABLE OF LS_FUPARAREF.
DATA : LV_REQ_JSON TYPE STRING.
DATA : LV_RET_JSON TYPE STRING.
DATA LV_SIGN(1) TYPE C.
DATA : LV_JSON_MSG TYPE STRING.
DATA : LV_HTML TYPE STRING.
LV_METHOD = SERVER->REQUEST->GET_HEADER_FIELD( NAME = '~request_method' ).
SERVER->REQUEST->GET_HEADER_FIELDS( CHANGING FIELDS = LT_FIELDS ).
"---解析url 参数 ~query_string
READ TABLE LT_FIELDS INTO LS_FIELDS WITH KEY NAME = '~query_string'.
IF SY-SUBRC = 0.
SPLIT LS_FIELDS-VALUE AT '&' INTO TABLE DATA(LT_QUERY_STRING).
LOOP AT LT_QUERY_STRING INTO DATA(LS_QUERY_STRING).
IF LS_QUERY_STRING CS 'sndprn' OR LS_QUERY_STRING CS 'zrfcid'.
CLEAR : LS_FIELDS.
SPLIT LS_QUERY_STRING AT '=' INTO LS_FIELDS-NAME LS_FIELDS-VALUE.
APPEND LS_FIELDS TO LT_FIELDS.
ENDIF.
ENDLOOP.
ENDIF.
LOOP AT LT_FIELDS INTO LS_FIELDS.
ASSIGN COMPONENT LS_FIELDS-NAME OF STRUCTURE LS_HEADER_FIELDS TO FIELD-SYMBOL(<FS_FIELD>).
IF <FS_FIELD> IS ASSIGNED.
<FS_FIELD> = LS_FIELDS-VALUE.
ENDIF.
UNASSIGN <FS_FIELD>.
ENDLOOP.
IF LS_HEADER_FIELDS-SNDPRN IS INITIAL.
LS_RESPONSE-CODE = 'E'.
LS_RESPONSE-MSG = 'SNDPRN不能为空!'.
ENDIF.
IF LS_HEADER_FIELDS-ZRFCID IS INITIAL.
LS_RESPONSE-CODE = 'E'.
LS_RESPONSE-MSG = 'ZRFCID不能为空!'.
ENDIF.
"获取配置的RFC函数名
SELECT
SINGLE
* FROM ZTURL_SCARR
WHERE PARNUM = @LS_HEADER_FIELDS-SNDPRN
AND ZRFCID = @LS_HEADER_FIELDS-ZRFCID
INTO @DATA(LS_URL).
IF SY-SUBRC NE 0 AND LS_HEADER_FIELDS-SNDPRN IS NOT INITIAL AND LS_HEADER_FIELDS-ZRFCID IS NOT INITIAL.
LS_RESPONSE-CODE = 'E'.
IF LS_RESPONSE-MSG IS INITIAL.
LS_RESPONSE-MSG = |{ LS_HEADER_FIELDS-SNDPRN }-{ LS_HEADER_FIELDS-ZRFCID }接口配置不存在|.
ELSE.
LS_RESPONSE-MSG = |{ LS_RESPONSE-MSG };{ LS_HEADER_FIELDS-SNDPRN }-{ LS_HEADER_FIELDS-ZRFCID }接口配置不存在|.
ENDIF.
ENDIF.
"获取函数的参数等信息
SELECT *
FROM FUPARAREF
WHERE FUNCNAME = @LS_URL-FUNC_NAME
INTO CORRESPONDING FIELDS OF TABLE @LT_FUPARAREF.
IF SY-SUBRC <> 0.
LS_RESPONSE-CODE = 'E'.
IF LS_RESPONSE-MSG IS INITIAL.
LS_RESPONSE-MSG = |接口对应RFC不存在|.
ELSE.
LS_RESPONSE-MSG = |{ LS_RESPONSE-MSG };接口对应RFC不存在|.
ENDIF.
ENDIF.
IF LS_RESPONSE-CODE EQ 'E'.
"---参数不全直接退出
CALL METHOD ME->_RESPONSE_JSON( SERVER = SERVER IV_JSON = LV_HTML DATA = LS_RESPONSE ).
RETURN.
ENDIF.
"---创建动态结构
CALL METHOD ME->_CREATE_DYNAMIC_STRU
EXPORTING
IV_FUNCNAME = LS_URL-FUNC_NAME " 功能模块的名称
IT_FUPARAREF = LT_FUPARAREF
IMPORTING
ER_REQ_STRUCT = LR_REQ
ER_RET_STRUCT = LR_RET.
IF LS_HEADER_FIELDS-GET_REQUEST_JSON EQ 'X'.
"---获取request_json格式示例
CALL METHOD ME->_GET_JSON_MSG(
EXPORTING
IR_REQ_STRUCT = LR_REQ
IMPORTING
EV_JSON_MSG = LV_JSON_MSG
).
CALL METHOD ME->_RESPONSE_JSON( SERVER = SERVER IV_JSON = LV_JSON_MSG DATA = LS_RESPONSE ).
RETURN.
ENDIF.
*-----获取传入报文
LV_REQ_JSON = SERVER->REQUEST->IF_HTTP_ENTITY~GET_CDATA( ).
IF LV_REQ_JSON IS INITIAL.
LS_RESPONSE-CODE = 'E'.
IF LS_RESPONSE-MSG IS INITIAL.
LS_RESPONSE-MSG = |传入报文不允许为空|.
ELSE.
LS_RESPONSE-MSG = |{ LS_RESPONSE-MSG };传入报文不允许为空|.
ENDIF.
ENDIF.
IF LS_RESPONSE-CODE = 'E'.
"---存在错误退出接口
CALL METHOD ME->_RESPONSE_JSON( SERVER = SERVER IV_JSON = LV_HTML DATA = LS_RESPONSE )..
RETURN.
ENDIF.
"---去除tab
LV_SIGN = CL_ABAP_CHAR_UTILITIES=>HORIZONTAL_TAB.
REPLACE ALL OCCURRENCES OF REGEX LV_SIGN IN LV_REQ_JSON WITH ``.
"---去除换行
LV_SIGN = CL_ABAP_CHAR_UTILITIES=>NEWLINE.
REPLACE ALL OCCURRENCES OF REGEX LV_SIGN IN LV_REQ_JSON WITH ``.
*&--------------------------post方法动态调用RFC-------------------------------&*
"---调用RFC
CALL METHOD ME->_CALL_FUNCTION(
EXPORTING
IV_REQ_JSON = LV_REQ_JSON
IV_FUNCNAME = LS_URL-FUNC_NAME " 功能模块的名称
IT_FUPARAREF = LT_FUPARAREF " 功能模块参数
IR_REQ_STRUCT = LR_REQ
IR_RET_STRUCT = LR_RET
IMPORTING
EV_RET_JSON = LV_RET_JSON " 返回json
).
CALL METHOD ME->_RESPONSE_JSON( SERVER = SERVER IV_JSON = LV_RET_JSON DATA = LS_RESPONSE ).
ENDMETHOD.
_CALL_FUNCTION

js
METHOD _CALL_FUNCTION.
DATA : LS_PTAB TYPE ABAP_FUNC_PARMBIND,
LT_PTAB TYPE ABAP_FUNC_PARMBIND_TAB.
DATA : LS_ETAB TYPE ABAP_FUNC_EXCPBIND,
LT_ETAB TYPE ABAP_FUNC_EXCPBIND_TAB.
DATA : LO_TYPEDESCR TYPE REF TO CL_ABAP_TYPEDESCR.
DATA : LS_FIELD_IN TYPE DFIES,
LT_DFIES TYPE DDFIELDS.
DATA : OBJEKT TYPE REF TO DATA.
DATA : LV_DATATYPE TYPE CHAR1.
DATA : LV_ERROR_MSG TYPE STRING.
FIELD-SYMBOLS: <FS_ABER> TYPE ANY.
FIELD-SYMBOLS: <FS_PARA_IN> TYPE ANY.
FIELD-SYMBOLS: <FS_PARA_OUT> TYPE ANY.
FIELD-SYMBOLS: <FS_ABER_TB> TYPE ANY.
ASSIGN IR_REQ_STRUCT->* TO FIELD-SYMBOL(<FS_REQ>).
ASSIGN IR_RET_STRUCT->* TO FIELD-SYMBOL(<FS_RET>).
*--------------------------------------------------------------------*
* 1 解析传入参数
*--------------------------------------------------------------------*
/UI2/CL_JSON=>DESERIALIZE( EXPORTING JSON = IV_REQ_JSON
CHANGING DATA = <FS_REQ> ).
*--------------------------------------------------------------------*
* 2 函数输入参数赋值
*--------------------------------------------------------------------*
LOOP AT IT_FUPARAREF INTO DATA(LS_FUPARAREF).
UNASSIGN: <FS_ABER>, <FS_PARA_IN>.
CLEAR: LV_DATATYPE, LO_TYPEDESCR.
"动态创建工作区、内表
IF LS_FUPARAREF-TYPE = 'X'.
CREATE DATA OBJEKT TYPE (LS_FUPARAREF-STRUCTURE).
ASSIGN OBJEKT->* TO <FS_ABER>.
ASSIGN COMPONENT LS_FUPARAREF-PARAMETER OF STRUCTURE <FS_REQ> TO <FS_PARA_IN>.
ELSE.
CREATE DATA OBJEKT TYPE TABLE OF (LS_FUPARAREF-STRUCTURE).
ASSIGN OBJEKT->* TO <FS_ABER>.
ASSIGN COMPONENT LS_FUPARAREF-PARAMETER OF STRUCTURE <FS_REQ> TO <FS_PARA_IN>.
ENDIF.
LO_TYPEDESCR ?= CL_ABAP_TYPEDESCR=>DESCRIBE_BY_DATA( <FS_ABER> ).
LV_DATATYPE = LO_TYPEDESCR->KIND.
IF LS_FUPARAREF-PARAMETER = 'I' AND LS_FUPARAREF-REFERENCE = 'X'.
CONTINUE.
ENDIF.
IF <FS_PARA_IN> IS ASSIGNED.
_CONVERSION_EXIT_INPUT(
CHANGING
CV_DATA = <FS_PARA_IN> ).
<FS_ABER> = <FS_PARA_IN>. "对指向传入参数的指针进行赋值,等于请求参数名对应的值
ENDIF.
" 对动态FM 参数赋值
LS_PTAB-VALUE = OBJEKT.
LS_PTAB-NAME = LS_FUPARAREF-PARAMETER.
CASE LS_FUPARAREF-PARAMTYPE.
WHEN 'I'.
LS_PTAB-KIND = ABAP_FUNC_EXPORTING.
WHEN 'C'.
LS_PTAB-KIND = ABAP_FUNC_CHANGING.
WHEN 'T'.
LS_PTAB-KIND = ABAP_FUNC_TABLES.
WHEN 'E'.
LS_PTAB-KIND = ABAP_FUNC_IMPORTING.
ENDCASE.
INSERT LS_PTAB INTO TABLE LT_PTAB.
CLEAR: LS_PTAB.
UNASSIGN: <FS_PARA_IN>, <FS_ABER_TB>.
ENDLOOP.
*--------------------------------------------------------------------*
* 3 调用函数
*--------------------------------------------------------------------*
TRY .
CALL FUNCTION IV_FUNCNAME
PARAMETER-TABLE LT_PTAB
EXCEPTION-TABLE LT_ETAB.
CATCH CX_SY_DYN_CALL_PARAM_NOT_FOUND INTO DATA(LO_ERROR_NO_FOUND).
LV_ERROR_MSG = LO_ERROR_NO_FOUND->GET_TEXT( ).
CATCH CX_SY_DYN_CALL_PARAM_MISSING INTO DATA(LO_ERROR_MISSING).
LV_ERROR_MSG = LO_ERROR_MISSING->GET_TEXT( ).
CATCH CX_SY_DYN_CALL_PARAMETER_ERROR INTO DATA(LO_ERROR_PARAMETER).
LV_ERROR_MSG = LO_ERROR_PARAMETER->GET_TEXT( ).
CATCH CX_SY_DYN_CALL_ERROR INTO DATA(LO_ERROR_CALL).
LV_ERROR_MSG = LO_ERROR_CALL->GET_TEXT( ).
ENDTRY.
*--------------------------------------------------------------------*
* 4 函数输出参数赋值
*--------------------------------------------------------------------*
LOOP AT IT_FUPARAREF INTO LS_FUPARAREF WHERE PARAMTYPE CA 'CET'.
" AND PARAMETER+0(1) EQ 'E'. "返回参数必须用E 开头,如果去掉这句就会一并显示表的内容,加上只出现E开头的返回参数
UNASSIGN: <FS_PARA_OUT>, <FS_ABER>.
CLEAR: LV_DATATYPE.
"动态创建工作区、内表
IF LS_FUPARAREF-TYPE = 'X'.
CREATE DATA OBJEKT TYPE (LS_FUPARAREF-STRUCTURE).
ASSIGN COMPONENT LS_FUPARAREF-PARAMETER OF STRUCTURE <FS_RET> TO <FS_PARA_OUT>.
ELSE.
CREATE DATA OBJEKT TYPE TABLE OF (LS_FUPARAREF-STRUCTURE).
ASSIGN COMPONENT LS_FUPARAREF-PARAMETER OF STRUCTURE <FS_RET> TO <FS_PARA_OUT>.
ENDIF.
READ TABLE LT_PTAB INTO LS_PTAB WITH KEY NAME = LS_FUPARAREF-PARAMETER.
IF SY-SUBRC = 0.
OBJEKT = LS_PTAB-VALUE.
ASSIGN OBJEKT->* TO <FS_ABER>.
ENDIF.
_CONVERSION_EXIT_OUTPUT(
CHANGING
CV_DATA = <FS_ABER>
).
<FS_PARA_OUT> = <FS_ABER> . "对指向传出参数的指针进行赋值
ENDLOOP.
CALL METHOD /UI2/CL_JSON=>SERIALIZE
EXPORTING
DATA = <FS_RET>
RECEIVING
R_JSON = EV_RET_JSON.
ENDMETHOD.
_CONVERSION_EXIT_INPUT

js
METHOD _CONVERSION_EXIT_INPUT.
" add by luf 20210706
DATA: lv_exclude_exit TYPE string VALUE 'ABPSP/ABPSN/EXCRT'. "按照项目需求做增强
DATA: lo_cl_abap_typedescr TYPE REF TO cl_abap_typedescr.
DATA: lo_cl_abap_elemdescr TYPE REF TO cl_abap_elemdescr.
DATA: lo_cl_abap_refdescr TYPE REF TO cl_abap_refdescr.
DATA: lo_cl_abap_structdescr TYPE REF TO cl_abap_structdescr.
DATA: lo_cl_abap_tabledescr TYPE REF TO cl_abap_tabledescr.
DATA: lo_cl_abap_classdescr TYPE REF TO cl_abap_classdescr.
DATA: lo_cl_abap_intfdescr TYPE REF TO cl_abap_intfdescr.
DATA: ls_zz_trans_comp_descr TYPE abap_componentdescr.
DATA: lt_zz_trans_comp_tab TYPE cl_abap_structdescr=>component_table.
DATA: lv_zz_trans_table_name TYPE string.
DATA: ls_zz_trans_fupararef TYPE fupararef,
lt_zz_trans_fupararef TYPE TABLE OF fupararef.
DATA: lo_zz_trans_root_error TYPE REF TO cx_root.
"因为通用名称,所以变量必须特殊
DATA: lv_zz_trans_funtion_name TYPE string.
FIELD-SYMBOLS: <fs_zz_trans_field> TYPE any.
FIELD-SYMBOLS: <fs_zz_trans_workarea> TYPE any.
FIELD-SYMBOLS : <pt_data> TYPE ANY TABLE.
IF cv_data IS NOT INITIAL.
"反射
lo_cl_abap_typedescr = cl_abap_typedescr=>describe_by_data( cv_data ).
CASE lo_cl_abap_typedescr->kind.
WHEN 'E'. "元素
lo_cl_abap_elemdescr ?= lo_cl_abap_typedescr.
IF lo_cl_abap_elemdescr->edit_mask IS NOT INITIAL AND lv_exclude_exit NS lo_cl_abap_elemdescr->edit_mask+2. "存在转换例程,且不在排除范围
lv_zz_trans_funtion_name = 'CONVERSION_EXIT_' && lo_cl_abap_elemdescr->edit_mask+2 && '_INPUT'.
TRY .
CALL FUNCTION lv_zz_trans_funtion_name
EXPORTING
input = cv_data
IMPORTING
output = cv_data
EXCEPTIONS
error_message = 99.
IF sy-subrc <> 0.
ENDIF.
CATCH cx_root INTO lo_zz_trans_root_error.
ENDTRY.
ENDIF.
WHEN 'S'."结构
"反射
lo_cl_abap_structdescr ?= cl_abap_typedescr=>describe_by_data( cv_data ).
lt_zz_trans_comp_tab[] = lo_cl_abap_structdescr->get_components( )."组成结构体的各个字段组件
LOOP AT lt_zz_trans_comp_tab INTO ls_zz_trans_comp_descr WHERE as_include = 'X'. "递归INCLUDE结构
lo_cl_abap_structdescr ?= ls_zz_trans_comp_descr-type.
APPEND LINES OF lo_cl_abap_structdescr->get_components( ) TO lt_zz_trans_comp_tab[].
ENDLOOP.
LOOP AT lt_zz_trans_comp_tab INTO ls_zz_trans_comp_descr.
IF ls_zz_trans_comp_descr-as_include = 'X'.
DELETE lt_zz_trans_comp_tab.
CONTINUE.
ENDIF.
"存在例程
ASSIGN COMPONENT ls_zz_trans_comp_descr-name OF STRUCTURE cv_data TO <fs_zz_trans_field>.
IF <fs_zz_trans_field> IS ASSIGNED.
_conversion_exit_input( CHANGING cv_data = <fs_zz_trans_field> ).
UNASSIGN <fs_zz_trans_field>.
ENDIF.
ENDLOOP.
WHEN 'T'."结构
IF cv_data IS NOT INITIAL.
ASSIGN cv_data TO <pt_data>.
IF <pt_data> IS ASSIGNED.
"转换处理
LOOP AT <pt_data> ASSIGNING <fs_zz_trans_workarea>.
_conversion_exit_input( CHANGING cv_data = <fs_zz_trans_workarea> ).
ENDLOOP.
ENDIF.
ENDIF.
WHEN OTHERS.
ENDCASE.
ENDIF.
ENDMETHOD.
_CONVERSION_EXIT_OUTPUT

js
METHOD _CONVERSION_EXIT_OUTPUT.
" add by luf 20210706
DATA: lv_exclude_exit TYPE string VALUE 'ABPSP/ABPSN/EXCRT'. "按照项目需求做增强
DATA: lo_cl_abap_typedescr TYPE REF TO cl_abap_typedescr.
DATA: lo_cl_abap_elemdescr TYPE REF TO cl_abap_elemdescr.
DATA: lo_cl_abap_refdescr TYPE REF TO cl_abap_refdescr.
DATA: lo_cl_abap_structdescr TYPE REF TO cl_abap_structdescr.
DATA: lo_cl_abap_tabledescr TYPE REF TO cl_abap_tabledescr.
DATA: lo_cl_abap_classdescr TYPE REF TO cl_abap_classdescr.
DATA: lo_cl_abap_intfdescr TYPE REF TO cl_abap_intfdescr.
DATA: ls_zz_trans_comp_descr TYPE abap_componentdescr.
DATA: lt_zz_trans_comp_tab TYPE cl_abap_structdescr=>component_table.
DATA: lv_zz_trans_table_name TYPE string.
DATA: ls_zz_trans_fupararef TYPE fupararef,
lt_zz_trans_fupararef TYPE TABLE OF fupararef.
DATA: lo_zz_trans_root_error TYPE REF TO cx_root.
"因为通用名称,所以变量必须特殊
DATA: lv_zz_trans_funtion_name TYPE string.
FIELD-SYMBOLS: <fs_zz_trans_field> TYPE any.
FIELD-SYMBOLS: <fs_zz_trans_workarea> TYPE any.
FIELD-SYMBOLS : <pt_data> TYPE ANY TABLE.
IF cv_data IS NOT INITIAL.
"反射
lo_cl_abap_typedescr = cl_abap_typedescr=>describe_by_data( cv_data ).
CASE lo_cl_abap_typedescr->kind.
WHEN 'E'. "元素
lo_cl_abap_elemdescr ?= lo_cl_abap_typedescr.
IF lo_cl_abap_elemdescr->edit_mask IS NOT INITIAL AND lv_exclude_exit NS lo_cl_abap_elemdescr->edit_mask+2. "存在转换例程,且不在排除范围
lv_zz_trans_funtion_name = 'CONVERSION_EXIT_' && lo_cl_abap_elemdescr->edit_mask+2 && '_OUTPUT'.
TRY .
CALL FUNCTION lv_zz_trans_funtion_name
EXPORTING
input = cv_data
IMPORTING
output = cv_data
EXCEPTIONS
error_message = 99.
IF sy-subrc <> 0.
ENDIF.
CATCH cx_root INTO lo_zz_trans_root_error.
ENDTRY.
ENDIF.
WHEN 'S'."结构
"反射
lo_cl_abap_structdescr ?= cl_abap_typedescr=>describe_by_data( cv_data ).
lt_zz_trans_comp_tab[] = lo_cl_abap_structdescr->get_components( )."组成结构体的各个字段组件
LOOP AT lt_zz_trans_comp_tab INTO ls_zz_trans_comp_descr WHERE as_include = 'X'. "递归INCLUDE结构
lo_cl_abap_structdescr ?= ls_zz_trans_comp_descr-type.
APPEND LINES OF lo_cl_abap_structdescr->get_components( ) TO lt_zz_trans_comp_tab[].
ENDLOOP.
LOOP AT lt_zz_trans_comp_tab INTO ls_zz_trans_comp_descr.
IF ls_zz_trans_comp_descr-as_include = 'X'.
DELETE lt_zz_trans_comp_tab.
CONTINUE.
ENDIF.
"存在例程
ASSIGN COMPONENT ls_zz_trans_comp_descr-name OF STRUCTURE cv_data TO <fs_zz_trans_field>.
IF <fs_zz_trans_field> IS ASSIGNED.
_conversion_exit_output( CHANGING cv_data = <fs_zz_trans_field> ).
UNASSIGN <fs_zz_trans_field>.
ENDIF.
ENDLOOP.
WHEN 'T'."结构
ASSIGN cv_data TO <pt_data>.
IF <pt_data> IS ASSIGNED.
"转换处理
LOOP AT <pt_data> ASSIGNING <fs_zz_trans_workarea>.
_conversion_exit_output( CHANGING cv_data = <fs_zz_trans_workarea> ).
ENDLOOP.
ENDIF.
WHEN OTHERS.
ENDCASE.
ENDIF.
ENDMETHOD.
_GET_JSON_MSG

js
METHOD _GET_JSON_MSG.
ASSIGN IR_REQ_STRUCT->* TO FIELD-SYMBOL(<FS_REQ>).
"--- <fs_req> 若有表则需要手动添加行
"---生成json报文
EV_JSON_MSG = /UI2/CL_JSON=>SERIALIZE( DATA = <FS_REQ>
NUMC_AS_STRING = 'X' ).
ENDMETHOD.
_RESPONSE_JSON

js
METHOD _RESPONSE_JSON.
DATA : LV_JSON TYPE STRING.
DATA : LS_RESPONSE TYPE ZSAPPO_RET_INFO.
IF IV_JSON IS INITIAL AND DATA IS INITIAL.
LS_RESPONSE-CODE = 'E'.
LS_RESPONSE-MSG = TEXT-001.
"生成JSON
LV_JSON = /UI2/CL_JSON=>SERIALIZE( DATA = LS_RESPONSE
PRETTY_NAME = /UI2/CL_JSON=>PRETTY_MODE-NONE ).
ELSEIF IV_JSON IS NOT INITIAL.
LV_JSON = IV_JSON.
ELSEIF DATA IS NOT INITIAL.
"生成JSON
LV_JSON = /UI2/CL_JSON=>SERIALIZE( DATA = DATA
PRETTY_NAME = /UI2/CL_JSON=>PRETTY_MODE-NONE ).
ENDIF.
"---添加相应报文
SERVER->RESPONSE->IF_HTTP_ENTITY~SET_CONTENT_TYPE( CONTENT_TYPE = 'application/json' ).
SERVER->RESPONSE->SET_CDATA(
EXPORTING
DATA = LV_JSON " Character data
).
ENDMETHOD.
_CREATE_DYNAMIC_STRU

js
METHOD _CREATE_DYNAMIC_STRU.
DATA: LS_COMPONENTS TYPE ABAP_COMPONENTDESCR,
LT_COMPONENTS TYPE ABAP_COMPONENT_TAB,
LO_ELEMT_TYPE TYPE REF TO CL_ABAP_DATADESCR.
DATA: LR_REQ TYPE REF TO DATA,
LR_RET TYPE REF TO DATA,
LR_ITAB TYPE REF TO DATA.
" RFC函数动态赋值结构
DATA: LS_PTAB TYPE ABAP_FUNC_PARMBIND,
LT_PTAB TYPE ABAP_FUNC_PARMBIND_TAB.
DATA: LT_ETAB TYPE ABAP_FUNC_EXCPBIND_TAB.
FIELD-SYMBOLS: <FS_ITAB> TYPE ANY,
<FS_REQ> TYPE ANY,
<FS_RET> TYPE ANY.
*&--------------------------创建动态传入结构-------------------------------&*
LOOP AT IT_FUPARAREF[] INTO DATA(LS_FUPARAREF) WHERE PARAMTYPE CA 'ICT'.
CLEAR: LS_COMPONENTS,LO_ELEMT_TYPE.
IF LS_FUPARAREF-TYPE = 'X'.
LO_ELEMT_TYPE ?= CL_ABAP_STRUCTDESCR=>DESCRIBE_BY_NAME( LS_FUPARAREF-STRUCTURE ).
ELSE.
CREATE DATA LR_ITAB TYPE TABLE OF (LS_FUPARAREF-STRUCTURE).
ASSIGN LR_ITAB->* TO <FS_ITAB>.
LO_ELEMT_TYPE ?= CL_ABAP_STRUCTDESCR=>DESCRIBE_BY_DATA( <FS_ITAB> ).
ENDIF.
LS_COMPONENTS-NAME = LS_FUPARAREF-PARAMETER.
LS_COMPONENTS-TYPE = LO_ELEMT_TYPE.
APPEND LS_COMPONENTS TO LT_COMPONENTS.
ENDLOOP.
DATA(LO_STRUCT) = CL_ABAP_STRUCTDESCR=>CREATE( P_COMPONENTS = LT_COMPONENTS ).
CREATE DATA ER_REQ_STRUCT TYPE HANDLE LO_STRUCT.
*&--------------------------创建动态传出结构-------------------------------&*
CLEAR: LT_COMPONENTS, LO_STRUCT.
LOOP AT IT_FUPARAREF[] INTO LS_FUPARAREF WHERE PARAMTYPE CA 'ECT'.
CLEAR: LS_COMPONENTS,LO_ELEMT_TYPE.
IF LS_FUPARAREF-TYPE = 'X'.
LO_ELEMT_TYPE ?= CL_ABAP_STRUCTDESCR=>DESCRIBE_BY_NAME( LS_FUPARAREF-STRUCTURE ).
ELSE.
CREATE DATA LR_ITAB TYPE TABLE OF (LS_FUPARAREF-STRUCTURE).
ASSIGN LR_ITAB->* TO <FS_ITAB>.
LO_ELEMT_TYPE ?= CL_ABAP_STRUCTDESCR=>DESCRIBE_BY_DATA( <FS_ITAB> ).
ENDIF.
LS_COMPONENTS-NAME = LS_FUPARAREF-PARAMETER.
LS_COMPONENTS-TYPE = LO_ELEMT_TYPE.
APPEND LS_COMPONENTS TO LT_COMPONENTS.
ENDLOOP.
LO_STRUCT = CL_ABAP_STRUCTDESCR=>CREATE( P_COMPONENTS = LT_COMPONENTS ).
CREATE DATA ER_RET_STRUCT TYPE HANDLE LO_STRUCT.
ENDMETHOD.
函数模块ZFC_SCARR_1
导入参数

导出参数

表

源代码
js
FUNCTION ZFC_SCARR_1.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(IV_FLAG) TYPE I DEFAULT 1
*" VALUE(IS_DATA) TYPE SCARR
*" EXPORTING
*" VALUE(ES_RET) TYPE ZSAPPO_RET_INFO
*" VALUE(EV_JSON) TYPE STRING
*" VALUE(EV_MATNR) TYPE MATNR
*" TABLES
*" IT_ITEMS STRUCTURE ZSL0001
*"----------------------------------------------------------------------
SELECT
DISTINCT
A~CARRID,
A~CARRNAME,
B~CONNID,
B~FLDATE,
B~CURRENCY
FROM SCARR AS A
LEFT JOIN SFLIGHT AS B ON A~CARRID = B~CARRID
WHERE A~CARRID = @IS_DATA-CARRID
INTO CORRESPONDING FIELDS OF TABLE @IT_ITEMS
UP TO 3 ROWS.
IF IT_ITEMS[] IS NOT INITIAL.
ES_RET-CODE = 'S'.
ES_RET-MSG = '恭喜!成功读取数据'.
ELSE.
ES_RET-CODE = 'E'.
ES_RET-MSG = '对不起,读取数据失败!'.
ENDIF.
SELECT SINGLE MATNR FROM MARA WHERE ERSDA = '20191024' INTO @EV_MATNR.
ENDFUNCTION.
Postman调试
请求参数

json
{
"IS_DATA": {
"MANDT": "",
"CARRID": "AA",
"CARRNAME": "AA航班",
"CURRCODE": "",
"URL": "https://www.url.com"
},
"IT_ITEMS": []
}
返回的JSON

json
{
"ES_RET": {
"RETKEYID": "",
"CODE": "S",
"MSG": "恭喜!成功读取数据",
"KEY1": "",
"KEY2": "",
"KEY3": "",
"RETMESSAGEID": ""
},
"EV_JSON": "",
"EV_MATNR": "169",
"IT_ITEMS": [
{
"CARRID": "AA",
"CARRNAME": "American Airlines",
"CONNID": 17,
"FLDATE": "2025-03-06",
"CURRENCY": "USD"
},
{
"CARRID": "AA",
"CARRNAME": "American Airlines",
"CONNID": 17,
"FLDATE": "2025-04-07",
"CURRENCY": "USD"
},
{
"CARRID": "AA",
"CARRNAME": "American Airlines",
"CONNID": 17,
"FLDATE": "2025-05-09",
"CURRENCY": "USD"
}
]
}