json - 使用 `CALL TRANSFORMATION` 在 ABAP 中自定义空值/初始值的序列化
问题描述
CALL TRANSFORMATION
您可以使用该命令将 ABAP 结构序列化为 JSON 。是否有可能序列化null
初始字段的值或忽略初始字段?
TYPES: BEGIN OF t_my_type,
foo TYPE string,
bar TYPE string,
END OF t_my_type.
DATA ls_structure TYPE t_my_type.
ls_structure-foo = 'some value'.
ASSERT ls_structure-bar IS INITIAL.
DATA(lo_json_writer) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE result = ls_structure RESULT XML lo_json_writer.
DATA(lv_json_xstring) = lo_json_writer->get_output( ).
WRITE cl_abap_codepage=>convert_from( source = lv_json_xstring ).
这个最小工作示例的结果是:
{
"RESULT": {
"FOO": "some value",
"BAR": ""
}
}
在其他语言(需要处理从 SAP 导出的 json)中,一个空字符串并不相同,""
并且null
确实需要我想避免的额外处理/处理。我想要这样的结果
{
"RESULT": {
"FOO": "some value",
"BAR": null
}
}
或忽略这样的初始值:
{
"RESULT": {
"FOO": "some value"
}
}
我可以通过一些额外的规则CALL TRANSFORMATION
来处理null
/initial 值吗?
解决方案
纯 ABAP 语言没有空值的概念,除了空引用。最接近的“概念”是初始值。
用于生成 JSON 格式的ID
转换永远不会从初始值生成 JSON 值“null”。空引用的序列化产生{}
,而其他类型产生""
(类型 C、STRING、X、XSTRING,最后两个用 base64 表示)、"000..."
(类型 N)、"0000-00-00"
(类型 D)、"00:00:00"
(类型 T)或0
(类型I, P, F, DECFLOAT16, DECFLOAT34, INT1, INT2, INT8)。
要仅序列化非初始值,您可以使用以下选项 initial_components = 'suppress'
:CALL TRANSFORMATION
CALL TRANSFORMATION ID
SOURCE result = ls_structure
RESULT XML lo_json_writer
OPTIONS initial_components = 'suppress'.
下面的程序演示了 JSON 值的区别,它们是初始值还是非初始值,以及何时使用选项initial_components = 'suppress'
。注意:为了序列化数据引用,我必须使用选项“data_refs = 'heap-or-create'`。
- 初始值:
{"RESULT":{"STRING":"","CHAR4":"","INT":0,"BINFLOAT":0,"DECFLOAT":0,"NUMC4":"0000","DATE":"0000-00-00","TIME":"00:00:00","XSTRING":"","HEX2":"","DREF":{},"OREF":{}}}
- 初始值 + 选项
initial_components = 'suppress'
:{"RESULT":{}}
- 非初始值:
{"RESULT":{"STRING":"a ","CHAR4":"b","INT":-1,"BINFLOAT":-2.9999999999999999E-1,"DECFLOAT":-0.3,"NUMC4":"0001","DATE":"2019-11-01","TIME":"10:49:00","XSTRING":"/w==","HEX2":"/w==","DREF":{"%ref":"#d1"},"OREF":{"%ref":"#o10"}},"%heap":{"o10":{"%type":"http://www.sap.com/abapxml/classes/program/ZDEMO_JSON_INITIAL:LCL_CLASS","%val":{"local.LCL_CLASS":{"ATTRIBUTE":"d"}}},"d1":{"%type":"abap:characters","%maxLength":1,"%val":"c"}}}
程序:
REPORT zdemo_json_initial.
TYPES: BEGIN OF t_my_type,
string TYPE string,
char4 TYPE c LENGTH 4,
int TYPE i,
binfloat TYPE f,
decfloat TYPE decfloat16,
numc4 TYPE n LENGTH 4,
date TYPE d,
time TYPE t,
xstring TYPE xstring,
hex2 TYPE x LENGTH 2,
dref TYPE REF TO data,
oref TYPE REF TO object,
END OF t_my_type.
CLASS lcl_class DEFINITION.
PUBLIC SECTION.
INTERFACES if_serializable_object.
DATA attribute TYPE string.
ENDCLASS.
DATA(initial) = value t_my_type( ).
DATA(oref) = NEW lcl_class( ).
oref->attribute = 'd'.
DATA(non_initial) = VALUE t_my_type( string = `a ` char4 = `b ` int = -1 binfloat = '-0.3'
decfloat = '-0.3' numc4 = '1' date = '20191101' time = '104900'
xstring = 'FF' hex2 = 'FF' dref = REF #( 'c' ) oref = oref ).
DATA(lo_json_writer1) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE result = initial RESULT XML lo_json_writer1
OPTIONS data_refs = 'heap-or-create'.
DATA(json_initial) = lo_json_writer1->get_output( ).
DATA(lo_json_writer2) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE result = initial RESULT XML lo_json_writer2
OPTIONS data_refs = 'heap-or-create' INITIAL_COMPONENTS = 'suppress'.
DATA(json_initial_suppress) = lo_json_writer2->get_output( ).
DATA(lo_json_writer3) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE result = non_initial RESULT XML lo_json_writer3
OPTIONS data_refs = 'heap-or-create'.
DATA(json_non_initial) = lo_json_writer3->get_output( ).
推荐阅读
- r - 如何为因子 x 轴构建带有渐变填充和顶部点/线的 geom_tile/rect 框?
- python - 如何在 tkinter 中设置 PanedWindow 内的默认帧大小?
- android - 使用 Progressive Web App,我可以检索手机的电话号码吗
- javascript - 不调用 WebRTC ontrack
- django - Django 验证并登录到您自己的网站
- vb.net - 可以为接口设置属性,但不能为从接口继承的对象设置属性(语音 API)
- javascript - 如何编写一个返回对象所有值的数组的函数
- php - 如何获取带有偏移量和限制的predis数据?
- javascript - 如何在 Javascript 中获取 SalesForce 选项列表依赖映射
- python - Flask-Migrate 未检测到表