关于ABAP调用LO_HTTP_CLIENT->RESPONSE->GET_DATA( )接收到乱码的解决方案
最近在处理SAP与外围系统的数据交互,其中发现涉及了几个要点。
1、abap转json发送。
2、json转abap接收。
3、接收到的json里的中文是乱码的问题。
1、SAP发送数据给外围系统时,有的要求要先获取token,有的不需要,笔者这里使用的是需要先获取token的情况,
此处获取token,外围系统会提供一个API,用户名,和密码,你要根据这三样去获取一个临时token。
这个时候你可以先用postman调用一下,看是否能正确获取。如果可以的话,开始组织ABAP代码,如果外围系统不多,可以直接写死API,用户名,和密码,
如果外围系统多的话,建议建立一个自建表,根据不同的外围系统名称去获取对应的API,用户名,和密码。这里以写死为例,代码如下:
"获取token DATA: LO_HTTP_CLIENT TYPE REF TO IF_HTTP_CLIENT, LV_LEN TYPE I, CONV TYPE REF TO CL_ABAP_CONV_IN_CE. DATA:LV_QUE_URL TYPE STRING. DATA:LV_QUE_STR TYPE STRING. DATA: LX_RESULT TYPE XSTRING, LV_RESULT TYPE STRING. DATA:V_I TYPE I, V_S TYPE STRING. LV_QUE_URL = 'http://IP:8088/seeyon/rest/token'. LV_QUE_STR = '{ "userName": "restsap", "password": "582420a8-e84e-4ee9-87fd-82289ce9f46b" }'. FREE:LO_HTTP_CLIENT. CL_HTTP_CLIENT=>CREATE_BY_URL( EXPORTING URL = LV_QUE_URL * ssl_id = 'ANONYM' IMPORTING CLIENT = LO_HTTP_CLIENT EXCEPTIONS ARGUMENT_NOT_FOUND = 1 PLUGIN_NOT_ACTIVE = 2 INTERNAL_ERROR = 3 OTHERS = 4 ). "设定传输请求内容格式以及编码格式 LO_HTTP_CLIENT->REQUEST->SET_CONTENT_TYPE( CONTENT_TYPE = 'application/json; charset=utf-8' ). "设定调用服务 LO_HTTP_CLIENT->REQUEST->SET_METHOD( IF_HTTP_REQUEST=>CO_REQUEST_METHOD_POST ). LO_HTTP_CLIENT->RESPONSE->IF_HTTP_ENTITY~SET_CONTENT_TYPE( CONTENT_TYPE = 'application/json' ). LV_LEN = STRLEN( LV_QUE_STR ). CALL METHOD LO_HTTP_CLIENT->REQUEST->SET_CDATA EXPORTING DATA = LV_QUE_STR OFFSET = 0 LENGTH = LV_LEN. LO_HTTP_CLIENT->SEND( EXCEPTIONS HTTP_COMMUNICATION_FAILURE = 1 HTTP_INVALID_STATE = 2 ). LO_HTTP_CLIENT->RECEIVE( EXCEPTIONS HTTP_COMMUNICATION_FAILURE = 1 HTTP_INVALID_STATE = 2 HTTP_PROCESSING_FAILED = 3 ). IF SY-SUBRC <> 0. ENDIF. CLEAR LV_RESULT . LX_RESULT = LO_HTTP_CLIENT->RESPONSE->GET_DATA( ). LO_HTTP_CLIENT->RESPONSE->GET_STATUS( IMPORTING CODE = V_I REASON = V_S ). CALL METHOD LO_HTTP_CLIENT->CLOSE. CHECK LX_RESULT IS NOT INITIAL. CALL METHOD CL_ABAP_CONV_IN_CE=>CREATE EXPORTING ENCODING = '8400' RECEIVING CONV = CONV. CONV->CONVERT( EXPORTING INPUT = LX_RESULT IMPORTING DATA = LV_RESULT ). "定义下和回传结构一致的ABAP结构 DATA: BEGIN OF LS_KV, BINDINGUSER TYPE STRING, ID TYPE STRING, END OF LS_KV. CHECK LV_RESULT IS NOT INITIAL. CALL METHOD /UI2/CL_JSON=>DESERIALIZE EXPORTING JSON = LV_RESULT PRETTY_NAME = /UI2/CL_JSON=>PRETTY_MODE-CAMEL_CASE CHANGING DATA = LS_KV.
2、根据获取到的token,发送外围系统数据。
DATA:LV_QUE_URL1 TYPE STRING.
"这里是网址拼接TOKEN的方式,有时候是传表头的方式,根据实际情况处理 LV_QUE_URL1 = 'http://IP:8088/seeyon/rest/pidaoResource/pidao?token='&& LS_KV-ID. "定义要传输的内表格式,需要转为json DATA:LV_QUE_STR1 TYPE STRING. TYPES: BEGIN OF T_DATAS2, KEY TYPE STRING, AMOUNT TYPE STRING, END OF T_DATAS2. TYPES: TT_DATAS2 TYPE STANDARD TABLE OF T_DATAS2 WITH DEFAULT KEY. DATA:LT_DATA TYPE STANDARD TABLE OF T_DATAS2, LS_DATA TYPE T_DATAS2. "这里可以换成取数模式 LS_DATA-KEY = '111'. LS_DATA-AMOUNT = '1000'. APPEND LS_DATA TO LT_DATA. CLEAR:LS_DATA. LS_DATA-KEY = '222'. LS_DATA-AMOUNT = '2000'. APPEND LS_DATA TO LT_DATA. TYPES: BEGIN OF T_JSON1, ACTION TYPE STRING, DATAS TYPE TT_DATAS2, END OF T_JSON1. DATA:LT_OUT TYPE STANDARD TABLE OF T_JSON1, LS_OUT TYPE T_JSON1. LS_OUT-ACTION = 'check'. LS_OUT-DATAS = LT_DATA. APPEND LS_OUT TO LT_OUT. ***内表->JSON CALL METHOD /UI2/CL_JSON=>SERIALIZE EXPORTING DATA = LS_OUT COMPRESS = ABAP_FALSE PRETTY_NAME = /UI2/CL_JSON=>PRETTY_MODE-LOW_CASE RECEIVING R_JSON = LV_QUE_STR1. *LV_QUE_STR1 = '{ "action": "check", "datas":[ { "key":"111","amount":"1000"},{ "key":"222","amount":"2000"}] }'. FREE:LO_HTTP_CLIENT. CL_HTTP_CLIENT=>CREATE_BY_URL( EXPORTING URL = LV_QUE_URL1 * ssl_id = 'ANONYM' IMPORTING CLIENT = LO_HTTP_CLIENT EXCEPTIONS ARGUMENT_NOT_FOUND = 1 PLUGIN_NOT_ACTIVE = 2 INTERNAL_ERROR = 3 OTHERS = 4 ). "设定传输请求内容格式以及编码格式 LO_HTTP_CLIENT->REQUEST->SET_CONTENT_TYPE( CONTENT_TYPE = 'application/json; charset=utf-8' ). "设定调用服务 LO_HTTP_CLIENT->REQUEST->SET_METHOD( IF_HTTP_REQUEST=>CO_REQUEST_METHOD_POST ). LO_HTTP_CLIENT->RESPONSE->IF_HTTP_ENTITY~SET_CONTENT_TYPE( CONTENT_TYPE = 'application/json' ). CLEAR:LV_LEN. LV_LEN = STRLEN( LV_QUE_STR1 ). CALL METHOD LO_HTTP_CLIENT->REQUEST->SET_CDATA EXPORTING DATA = LV_QUE_STR1 OFFSET = 0 LENGTH = LV_LEN. LO_HTTP_CLIENT->SEND( EXCEPTIONS HTTP_COMMUNICATION_FAILURE = 1 HTTP_INVALID_STATE = 2 ). LO_HTTP_CLIENT->RECEIVE( EXCEPTIONS HTTP_COMMUNICATION_FAILURE = 1 HTTP_INVALID_STATE = 2 HTTP_PROCESSING_FAILED = 3 ). IF SY-SUBRC <> 0. ENDIF. CLEAR:V_I , V_S . CLEAR LV_RESULT . LX_RESULT = LO_HTTP_CLIENT->RESPONSE->GET_DATA( ). LO_HTTP_CLIENT->RESPONSE->GET_STATUS( IMPORTING CODE = V_I REASON = V_S ). CALL METHOD LO_HTTP_CLIENT->CLOSE.
3、解析外围系统返回的数据
CHECK LX_RESULT IS NOT INITIAL. "解析JSON串 CLEAR:LV_RESULT. CALL METHOD CL_ABAP_CONV_IN_CE=>CREATE EXPORTING ENCODING = '4110' RECEIVING CONV = CONV. CONV->CONVERT( EXPORTING INPUT = LX_RESULT IMPORTING DATA = LV_RESULT ). CHECK LV_RESULT IS NOT INITIAL. "定义下和回传结构一致的ABAP结构 TYPES: BEGIN OF T_INPUT_SON, AMOUNT TYPE STRING, CODE TYPE STRING, MESSAGE TYPE STRING, KEY TYPE STRING, END OF T_INPUT_SON. TYPES: TT_INPUT_SON TYPE STANDARD TABLE OF T_INPUT_SON WITH DEFAULT KEY. DATA:LT_DATA_SON TYPE STANDARD TABLE OF T_INPUT_SON, LS_DATA_SON TYPE T_INPUT_SON. TYPES: BEGIN OF T_ABAP, SUCCESSLIST TYPE TT_INPUT_SON, END OF T_ABAP. DATA:LT_INPUT TYPE STANDARD TABLE OF T_ABAP, LS_INPUT TYPE T_ABAP. CALL METHOD /UI2/CL_JSON=>DESERIALIZE EXPORTING JSON = LV_RESULT PRETTY_NAME = /UI2/CL_JSON=>PRETTY_MODE-CAMEL_CASE CHANGING DATA = LS_INPUT. LOOP AT LS_INPUT-SUCCESSLIST INTO DATA(LS_INPUT-SUCCESSLIST_1). WRITE:/ LS_INPUT-SUCCESSLIST_1-KEY,/ LS_INPUT-SUCCESSLIST_1-AMOUNT. ENDLOOP.
上面的4110怎么来的呢,这个是根据外围系统发送的字符格式来做对应的处理。
去SAP里查看TCP00的表
这里查出UTF-8的SAP 字符集标识为4110,所以使用这个进行转换下。
当然这个类/UI2/CL_JSON的序列化及反序列化网上都有,其中有个注意点是可能外围系统是驼峰命名,这里需要加入参数PRETTY_NAME,里面有大小写,驼峰等形式。