如今,JSON 格式正被广泛使用。您最终会需要使用 SAP ABAP 来解释 JSON 数据或创建 JSON 数据。
在本篇文章中,您将了解如何做到这一点。
- 验证 JSON
- 读取 JSON
- 创建 JSON
首先,让我们看看什么是 JSON 数据。你可以访问 json.org 了解有关 JSON 的更多信息。下面是一个简短的版本。
- JSON - JavaScript 对象符号
- 它是一种轻量级数据交换格式
- 便于人类读写
- 便于机器解析和生成
- 它基于 JavaScript 编程语言标准的一个子集
- JSON 基于两种结构
- 键-值对的集合
- 值的有序列表
JSON 示例
第一个示例有一组键和值对。这些值对分别是 name&Amar、age&18 以及 city & Mumbai。
{
"name": "Amar",
"age": 18,
"city": "Mumbai"
}
下面的第二个示例显示了第一个示例中的集合列表。JSON 中的每个值既可以是直接值,也可以是包含在 [ ]中的键-值对/集合列表,并用逗号" ,"分隔。
{
"students": [{
"name": "Amar",
"age": 18,
"city": "Mumbai"
},
{
"name": "Akbar",
"age": 17,
"city": "Mumbai"
},
{
"name": "Anthony",
"age": 16,
"city": "Mumbai"
}
]
}
jsonlint.com/ 或 jsonformatter.org/ 等网站可用于验证 JSON 数据或格式化 JSON 数据,以便我们进行测试。
JSON vs XML
JSON 与 XML 非常相似,都是人类可读的,都是分层的,都可用于各种编程语言。但 JSON 比 XML 更简单,它不使用结束标记,因此更短、读写更简单。
现在,让我们回到如何在 ABAP 中处理 JSON。
在 ABAP 中验证 JSON 数据
ABAP 中用于处理 JSON 的类是 cl_sxml_string_reader。由于 JSON 和 XML 相似,因此两者使用相同的类。
代码示例:
REPORT zjson_learning.
DATA : lv_json TYPE string VALUE '{"name": "Amar","age":18,"city": "Mumbai"}'.
DATA(lo_reader) = cl_sxml_string_reader=>create( cl_abap_codepage=>convert_to( lv_json ) ).
TRY.
lo_reader->next_node( ).
lo_reader->skip_node( ).
cl_demo_output=>display( 'JSON is valid' ).
CATCH cx_sxml_parse_error INTO DATA(lx_parse_error).
cl_demo_output=>display( lx_parse_error->get_text( ) ).
ENDTRY.
当 JSON 有效时,我们会得到以下输出:
然后更改 JSON 文件,尝试使用无效 JSON,得到如下输出结果。
DATA : lv_string TYPE string VALUE '{"name": "Amar","age":18,"city": "Mumbai"1}'.
然后更改 JSON 文件,尝试使用无效 JSON,得到如下输出结果:
使用 ABAP 读取 JSON
读取具有线性结构的 JSON 文件可能不是实际用例,但有助于理解代码块。
TYPES :
BEGIN OF ty_student,
name TYPE string,
age TYPE i,
city TYPE string,
END OF ty_student.
DATA : lv_json TYPE string VALUE '{"name": "Amar","age":18,"city": "Mumbai"}',
lr_data TYPE REF TO data,
ls_student TYPE ty_student.
/ui2/cl_json=>deserialize(
EXPORTING
json = lv_json
pretty_name = /ui2/cl_json=>pretty_mode-user
assoc_arrays = abap_true
CHANGING
data = lr_data ).
IF lr_data IS BOUND.
ASSIGN lr_data->* TO FIELD-SYMBOL(<lfs_data>).
DO 3 TIMES. "Number of fields
CASE sy-index.
WHEN 1. DATA(lv_fname) = 'NAME'.
WHEN 2. lv_fname = 'AGE'.
WHEN 3. lv_fname = 'CITY'.
ENDCASE.
ASSIGN COMPONENT sy-index OF STRUCTURE ls_student TO FIELD-SYMBOL(<lfs_field>).
ASSIGN COMPONENT lv_fname OF STRUCTURE <lfs_data> TO FIELD-SYMBOL(<lfs_ref_value>).
IF <lfs_ref_value> IS ASSIGNED AND <lfs_field> IS ASSIGNED.
lr_data = <lfs_ref_value>.
ASSIGN lr_data->* TO FIELD-SYMBOL(<lfs_actual_value>).
IF <lfs_actual_value> IS ASSIGNED.
<lfs_field> = <lfs_actual_value>.
ENDIF.
ENDIF.
ENDDO.
cl_demo_output=>display( ls_student ).
ENDIF.
输出结果:
当我们知道需要表格形式的数据时,我们可以使用内部表格而不是结构。我们需要不断地将数据从数据引用移动到字段符号,以读取数据值。
TYPES :
BEGIN OF ty_student,
name TYPE string,
age TYPE i,
city TYPE string,
END OF ty_student.
DATA : lv_json TYPE string,
lr_data TYPE REF TO data,
ls_student TYPE ty_student,
lt_student TYPE STANDARD TABLE OF ty_student.
FIELD-SYMBOLS : <lfs_table> TYPE ANY TABLE.
"Prepare JSON string for testing
lv_json = '{"students": [{"name": "Amar","age": 18,"city": "Mumbai"},' &&
'{"name": "Akbar","age": 17,"city": "Mumbai"},' &&
'{"name": "Anthony","age": 16,"city": "Mumbai"} ] }'.
/ui2/cl_json=>deserialize(
EXPORTING
json = lv_json
pretty_name = /ui2/cl_json=>pretty_mode-user
assoc_arrays = abap_true
CHANGING
data = lr_data ).
IF lr_data IS BOUND.
ASSIGN lr_data->* TO FIELD-SYMBOL(<lfs_data>).
ASSIGN COMPONENT 'STUDENTS' OF STRUCTURE <lfs_data> TO FIELD-SYMBOL(<lfs_results>).
ASSIGN <lfs_results>->* TO <lfs_table>.
LOOP AT <lfs_table> ASSIGNING FIELD-SYMBOL(<lfs_row>).
DO 3 TIMES. "Number of fields
CASE sy-index.
WHEN 1. DATA(lv_fname) = 'NAME'.
WHEN 2. lv_fname = 'AGE'.
WHEN 3. lv_fname = 'CITY'.
ENDCASE.
ASSIGN COMPONENT sy-index OF STRUCTURE ls_student TO FIELD-SYMBOL(<lfs_field>).
ASSIGN <lfs_row>->* TO FIELD-SYMBOL(<lfs_row_val>).
ASSIGN COMPONENT lv_fname OF STRUCTURE <lfs_row_val> TO FIELD-SYMBOL(<lfs_ref_value>).
IF <lfs_ref_value> IS ASSIGNED AND <lfs_field> IS ASSIGNED.
ASSIGN <lfs_ref_value>->* TO FIELD-SYMBOL(<lfs_actual_value>).
IF <lfs_actual_value> IS ASSIGNED.
<lfs_field> = <lfs_actual_value>.
ENDIF.
ENDIF.
ENDDO.
APPEND ls_student TO lt_student.
ENDLOOP.
cl_demo_output=>display( lt_student ).
ENDIF.
这是最佳解决方案吗?也许不是,但它足以让我们开始构建一个解决方案。
使用 ABAP 创建 JSON
SELECT * FROM scarr INTO TABLE @DATA(lt_scarr) UP TO 3 ROWS .
DATA(lv_json) = /ui2/cl_json=>serialize(
data = lt_scarr
compress = abap_true
pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
" Display JSON in ABAP
CALL TRANSFORMATION sjson2html SOURCE XML lv_json
RESULT XML DATA(lvc_html).
cl_abap_browser=>show_html(
title = 'Sample JSON'
html_string = cl_abap_codepage=>convert_from( lvc_html ) ).
还有更多选择。
CALL TRANSFORMATION
在上面的示例中,我们使用转换将 json 显示为 HTML。在这里,我们将把它用作 itab 到 JSON 的转换。
SELECT * FROM scarr INTO TABLE @DATA(lt_scarr).
DATA(lo_writer) =
cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id
SOURCE values = lt_scarr
RESULT XML lo_writer.
cl_abap_conv_in_ce=>create( )->convert(
EXPORTING
input = lo_writer->get_output( )
IMPORTING
data = lv_json ).
在调试模式下,JSON 字符串显示如下。
然后可以使用相同的 json 字符串来测试反向转换。
CLEAR lt_scarr.
CALL TRANSFORMATION id
SOURCE XML lv_json
RESULT values = lt_scarr.
cl_demo_output=>display( lt_scarr ).
执行结果:
下一步是研究 CL_SXML_TABLE_READER 类,以及如何使用它来获取特定数据。SAP 在软件包 SXML_DEMO 中创建了示例程序,并创建了以 DEMO_JSON_* 开头的程序。