ABAP JSON解析

ABAP JSON解析

概述

在 ABAP 中,可以使用标准类 /ui2/cl_json 进行 JSON 数据的序列化和反序列化操作,实现 ABAP 数据结构与 JSON 字符串之间的相互转换。

ℹ️类说明
/ui2/cl_json 是 SAP 提供的标准工具类,支持:
  • ABAP 结构/内表 → JSON 字符串(序列化)
  • JSON 字符串 → ABAP 结构/内表(反序列化)

序列化 serialize

使用 /ui2/cl_json=>serialize 方法将 ABAP 结构或内表转换为 JSON 字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DATA: lv_json TYPE string,
ls_data TYPE my_structure.

" 填充数据
ls_data-field1 = 'Value1'.
ls_data-field2 = 'Value2'.

" 序列化为 JSON
lv_json = /ui2/cl_json=>serialize(
data = ls_data
pretty_name = /ui2/cl_json=>pretty_mode-none
).

" 输出结果
WRITE: / lv_json.
" 结果: {"FIELD1":"Value1","FIELD2":"Value2"}

参数说明

参数 类型 说明
data 任意 要序列化的 ABAP 数据对象(结构或内表)
pretty_name ENUM JSON 字段命名格式模式
compress CHAR 是否压缩输出(X=压缩, =格式化)
assoc_arrays CHAR 是否保持数组顺序

pretty_name 字段名格式

模式 说明 示例
pretty_mode-none 保持原始字段名 FIELD_NAMEFIELD_NAME
pretty_mode-low_case 字段名转为小写 FIELD_NAMEfield_name
pretty_mode-camel_case 字段名转为驼峰命名 FIELD_NAMEfieldName

格式对比示例

1
2
3
4
5
6
7
8
9
10
" 原始 ABAP 结构字段: DOC_TYPE, DOC_ID, CREATED_AT

" pretty_mode-none
{"DOC_TYPE":"INV","DOC_ID":"12345","CREATED_AT":"2026-04-23"}

" pretty_mode-low_case
{"doc_type":"INV","doc_id":"12345","created_at":"2026-04-23"}

" pretty_mode-camel_case
{"DocType":"INV","DocId":"12345","CreatedAt":"2026-04-23"}

反序列化 deserialize

使用 /ui2/cl_json=>deserialize 方法将 JSON 字符串转换回 ABAP 数据结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DATA: lv_json TYPE string,
ls_data TYPE my_structure.

" JSON 字符串
lv_json = `{"FIELD1":"Value1","FIELD2":"Value2"}`.

" 反序列化为结构
/ui2/cl_json=>deserialize(
EXPORTING
json = lv_json
pretty_name = /ui2/cl_json=>pretty_mode-none
CHANGING
data = ls_data
).

" 使用数据
WRITE: / ls_data-field1, ls_data-field2.

参数说明

参数 类型 说明
json STRING 要反序列化的 JSON 字符串
pretty_name ENUM JSON 字段命名格式(需与序列化时一致)
data 任意 接收数据的 ABAP 数据对象(CHANGING 参数)
⚠️类型匹配
确保目标结构/内表的字段类型与 JSON 数据匹配,否则可能导致:
  • 转换失败
  • 数据丢失
  • 类型不兼容错误

完整示例

示例1: 基础序列化/反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
TYPES: BEGIN OF ts_person,
name TYPE string,
age TYPE i,
email TYPE string,
END OF ts_person.

DATA: ls_person TYPE ts_person,
lt_person TYPE STANDARD TABLE OF ts_person,
lv_json TYPE string.

" 序列化:结构 → JSON
ls_person-name = '张三'.
ls_person-age = 30.
ls_person-email = 'zhangsan@example.com'.

lv_json = /ui2/cl_json=>serialize(
data = ls_person
pretty_name = /ui2/cl_json=>pretty_mode-camel_case
).
" 结果: {"Name":"张三","Age":30,"Email":"zhangsan@example.com"}

" 反序列化:JSON → 结构
CLEAR ls_person.
/ui2/cl_json=>deserialize(
EXPORTING
json = lv_json
pretty_name = /ui2/cl_json=>pretty_mode-camel_case
CHANGING
data = ls_person
).

示例2: 内表序列化/反序列化

1
2
3
4
5
6
7
8
9
10
" 准备内表数据
APPEND VALUE #( name = '张三' age = 30 email = 'zhangsan@example.com' ) TO lt_person.
APPEND VALUE #( name = '李四' age = 28 email = 'lisi@example.com' ) TO lt_person.

" 序列化内表
lv_json = /ui2/cl_json=>serialize(
data = lt_person
pretty_name = /ui2/cl_json=>pretty_mode-low_case
).
" 结果: [{"name":"张三","age":30,"email":"zhangsan@example.com"},...]

示例3: 与外部系统交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
TYPES: BEGIN OF ts_import_data,
doc_type TYPE string,
doc_id TYPE string,
amount TYPE string,
currency TYPE string,
END OF ts_import_data.

TYPES: BEGIN OF ts_export_data,
status TYPE string,
message TYPE string,
timestamp TYPE string,
END OF ts_export_data.

DATA: lv_import_json TYPE string,
ls_import_data TYPE ts_import_data,
lv_export_json TYPE string,
ls_export_data TYPE ts_export_data.

" 导入:处理外部系统的 JSON
lv_import_json = `{
"docType": "INV",
"docId": "12345",
"amount": "1000.00",
"currency": "USD"
}`.

/ui2/cl_json=>deserialize(
EXPORTING
json = lv_import_json
pretty_name = /ui2/cl_json=>pretty_mode-camel_case
CHANGING
data = ls_import_data
).

" 导出:生成返回 JSON
ls_export_data-status = 'SUCCESS'.
ls_export_data-message = 'Data processed successfully'.
ls_export_data-timestamp = |{ sy-datum DATE = ISO }T{ sy-uzeit TIME = ISO }|.

lv_export_json = /ui2/cl_json=>serialize(
data = ls_export_data
pretty_name = /ui2/cl_json=>pretty_mode-none
).

最佳实践

💡字段名映射
与外部系统(JavaScript/Web服务)交互时,建议使用 pretty_mode-camel_case 保持与 JSON 的命名约定一致。
💡数据校验
反序列化后务必对关键字段进行校验:
1
2
3
IF ls_import_data-doc_id IS INITIAL.
" 处理错误情况
ENDIF.
💡性能优化
  • 大数据量使用 compress = abap_true 减少传输大小
  • 避免嵌套过深的结构
  • 考虑使用 ST 传输二进制数据
💡错误处理
1
2
3
4
5
6
7
8
9
DATA: lx_json TYPE REF TO cx_sy_move_cast_error.

TRY.
/ui2/cl_json=>deserialize(
EXPORTING json = lv_json
CHANGING data = ls_data ).
CATCH cx_sy_move_cast_error INTO lx_json.
WRITE: / 'JSON解析错误:', lx_json->get_text( ).
ENDTRY.

常见问题

Q: 如何处理嵌套 JSON?

定义嵌套的结构体类型即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
TYPES: BEGIN OF ts_address,
city TYPE string,
street TYPE string,
zip TYPE string,
END OF ts_address.

TYPES: BEGIN OF ts_person,
name TYPE string,
age TYPE i,
address TYPE ts_address,
END OF ts_person.

DATA: ls_person TYPE ts_person.

Q: 如何处理数组?

使用内表类型:

1
2
3
4
5
6
7
8
9
10
TYPES: BEGIN OF ts_item,
item_id TYPE string,
quantity TYPE i,
unit_price TYPE f,
END OF ts_item.

TYPES: BEGIN OF ts_order,
order_id TYPE string,
items TYPE STANDARD TABLE OF ts_item WITH EMPTY KEY,
END OF ts_order.

Q: 如何处理日期时间格式?

转换为标准字符串格式:

1
2
3
" 使用 ISO 8601 格式
DATA(lv_timestamp) = |{ sy-datum DATE = ISO }T{ sy-uzeit TIME = ISO }|.
" 结果: 2026-04-23T14:30:00