ABAP调用HTTP服务返回JSON含特殊字符/重音符号乱码问题
碰到过好多次这种ABAP里HTTP调用后特殊字符(比如重音符号)乱码的情况,看你给出的示例里éxito应该是éxito,COCHAMÓ对应COCHAMÓ——这明显是编码不匹配导致的,大概率是HTTP服务返回的UTF-8编码数据,被ABAP用了默认的ISO-8859-1(Latin-1)编码解析了。下面给你几个实操性强的解决步骤:
1. 先确认HTTP服务的响应编码
首先要搞清楚服务实际返回的字符编码,最直接的方式是检查响应的Content-Type头。规范的服务会返回类似:
Content-Type: application/json; charset=utf-8
在ABAP里可以通过cl_http_client获取这个头字段:
DATA(lo_http_client) = cl_http_client=>create_by_url( iv_url = '你的目标服务URL' ). lo_http_client->send( ). lo_http_client->receive( ). * 获取Content-Type头 DATA(lv_content_type) TYPE string. lo_http_client->response->get_header_field( EXPORTING name = 'Content-Type' IMPORTING value = lv_content_type ). WRITE lv_content_type. " 查看输出里是否包含charset=utf-8
如果头里没指定charset,服务很大概率返回的是UTF-8,但ABAP会用系统默认编码(很多老系统是ISO-8859-1)解析,这就是乱码的根源。
2. 强制用正确编码读取响应内容
不要直接用response->get_cdata()(这个方法会自动用系统默认或头里指定的编码转换),而是先获取二进制响应数据,再显式用服务的编码(通常是UTF-8)转换为ABAP字符串:
方法一:用转换类手动转(兼容旧版本ABAP)
* 获取原始二进制响应数据 DATA(lv_raw_data) TYPE xstring. lv_raw_data = lo_http_client->response->get_data( ). * 用UTF-8编码转换为字符串 DATA(lo_conv) = cl_abap_conv_in_ce=>create( encoding = 'UTF-8' ). DATA(lv_json_str) TYPE string. TRY. lv_json_str = lo_conv->convert( lv_raw_data ). CATCH cx_sy_conversion_codepage INTO DATA(lx_conv_err). WRITE '编码转换出错:' && lx_conv_err->get_text( ). ENDTRY.
方法二:用get_text直接指定编码(ABAP 7.50+可用)
新版本ABAP提供了更简洁的方法,直接指定编码读取文本:
DATA(lv_json_str) TYPE string. lv_json_str = lo_http_client->response->get_text( iv_encoding = 'UTF-8' ).
3. 确保JSON解析工具用正确编码
如果你用的是/ui2/cl_json或者其他JSON解析类,要确保解析时基于已经转换好的UTF-8字符串。比如:
DATA(lo_result) TYPE REF TO zcl_your_json_structure. " 你的目标数据结构 /ui2/cl_json=>deserialize( EXPORTING json = lv_json_str pretty_name = /ui2/cl_json=>pretty_mode-camel_case " 可选,根据结构调整命名规则 CHANGING data = lo_result ).
不要直接把get_cdata()返回的乱码字符串传给解析工具,那样只会让问题更复杂。
4. 系统编码兜底检查
如果上面的方法都没解决,那可能是你的ABAP系统默认编码不是UTF-8。可以通过事务码RZ10查看系统参数zcsa/system_locale和zcsa/second_locale,确认系统是否支持UTF-8。如果系统本身是ISO-8859-1编码,处理UTF-8数据时必须严格显式转换,不能依赖默认行为。
验证小技巧
你可以拿乱码的字符串(比如éxito)反过来测试:把它转成二进制,再用UTF-8转回来,看是否得到正确的éxito,这样能快速确认编码不匹配的方向。
内容的提问来源于stack exchange,提问作者Ivan Diaz Salas

