笔者之前的文章,保姆级教程:ABAP 通过 HTTP POST 调用 OData 服务创建业务数据的具体例子,我编写的 OData 工具类 zcl_odata_tool,其 create_opp 方法,最后返回的是 ABAP 后台成功创建的 Opportunity 数据,即 JSON 格式的字符串:
上图这些字段名称大小写相关,定义在 Opportunity OData 服务元数据里,可以通过事务码 SEGW 查看,即下图 Opportunity->Properties 文件夹下:
有一位读者,打算将我工具类返回的创建成功的 Opportunity JSON 字符串,反序列化成 ABAP 结构。
这种 ABAP 和 JSON 格式之间的序列化和反序列化工作,通过 SAP 标准工具类 /ui2/cl_json 对应的方法来完成。
代码如下:
TYPES: BEGIN OF ty_response,
d TYPE cl_crm_opportunity_mpc=>ts_opportunity,
END OF ty_response.
DATA: ls_response TYPE ty_response.
/ui2/cl_json=>deserialize( EXPORTING json = lv_created_opp CHANGING data = ls_response ).
这里我们需要手动定义一个新的 ABAP 类型 ty_response, 因为从 ABAP Gateway 返回的数据结构能看出,在实际的 Opportunity 业务数据外面,又包了额外一层,这一层的字段名称为 d,也就是下图图例 1 标注的字段。
该字段的值才是实际的创建成功的 Opportunity 业务数据。
所以进行反序列化时,用来接收反序列化结构的 ABAP 结构,也要体现出对应的这种结构。
执行 ABAP 报表之后,发现反序列化得到的 ABAP 结构里,只有 GUID,DESCRIPTION 和 STARTDATE 这几个字段有值。
仔细比较 JSON 字符串的字段名称和用来接收反序列化结果的 ABAP 结构内的字段名称,发现反序列化成功的三个字段,恰好都是其 JSON 和 ABAP 结构,字段名称完全一致的情况(不考虑大小写)。
回过头研究 /ui2/cl_json 的 deserialize 方法,果然发现一个名叫 name_mappings 的输入参数。
这个参数类型是一个哈希表,表的行项目,负责维护 ABAP 和 JSON 端的映射关系。
所以遇到 ABAP 和 JSON 端字段名称不一致的情况,只需要维护这张命名映射表,传递给 /ui2/cl_json 的 deserialize 方法,后者在反序列化时,就知道如何应对。
改进后的源代码为:
TYPES: BEGIN OF ty_response,
d TYPE cl_crm_opportunity_mpc=>ts_opportunity,
END OF ty_response.
DATA: ls_response TYPE ty_response.
DATA: lt_mapping TYPE /ui2/cl_json=>name_mappings,
ls_mapping LIKE LINE OF lt_mapping.
ls_mapping-abap = 'OBJECT_ID'.
ls_mapping-json = 'Id'.
INSERT ls_mapping INTO TABLE lt_mapping.
ls_mapping-abap = 'PROCESS_TYPE'.
ls_mapping-json = 'ProcessType'.
INSERT ls_mapping INTO TABLE lt_mapping.
/ui2/cl_json=>deserialize( EXPORTING json = lv_created_opp name_mappings = lt_mapping CHANGING data = ls_response ).
这一次,维护了同 ABAP 字段映射关系的 Id 和 ProcessType 这两个 JSON 字段,其反序列化后对应的 OBJECT_ID 和 PROCESS_TYPE 这两个 ABAP 字段,也填充上对应的值了。
/ui2/cl_json 类的 deserialize 方法内部,采用了递归的方式,实现了 JSON 数据的反序列化。
大家如果对其实现细节感兴趣,可以拜托 ChatGPT 生成详细的源码分析和解读报告。
首先把完整的源代码扔给 ChatGPT,让其理解。
/ui2/cl_json 完整的源代码,在 Github 上能找到:
https://github.com/fidley/JSON2ABAPType/blob/master/src/zui2_json.clas.abap
请你扮演一个资深的 ABAP 技术专家,我给你发送一个 class 的完整源代码,请你对它进行理解,然后等待我进一步的指令。
通过阅读源代码,ChatGPT 已经判断出这个类实现了 JSON 和 ABAP 数据结构之间的转换逻辑。
接下来让 ChatGPT 按照类似图的深度优先遍历方式,对源代码逐行进行解读:
请你详细分析方法 DESERIALIZE 的实现原理,通过分析源代码的方式进行解释。如果这个方法的源代码,调用到了新的方法,请你进行新的方法继续分析,直至该方法涉及到的所有方法都已经分析完毕。分析方法的时候,请逐行介绍该行语句实现的功能。
利用这种方法,可以通过研读 SAP 高质量的代码,来提高自己的编码水平。