正在将JSON字符串反序列化为ABAP中的结构



我想将JSON字符串反序列化为如下定义的结构:

TYPES: BEGIN OF json_subobject,
c TYPE i,
d TYPE decfloat34,
END OF json_subobject.
TYPES: BEGIN OF json_object,
a TYPE c LENGTH 10,
b TYPE json_subobject,
END OF json_object.
DATA: foo TYPE json_object.

我在JSON中对这种结构建模如下:

{
"a":"FooBar",
"b":{
"c":9,
"d":3.14
}
}

现在,我编写了一个简单的程序,在上面的JSON上试用CALL TRANSFORMATION语句,并附带上面的结构定义。程序应该反序列化JSON(硬编码到变量lv_xmls中(,并打印出结果结构的内容。结构的内容应该与原始JSON的内容相匹配。这就是程序:

TYPES: BEGIN OF json_subobject,
c TYPE i,
d TYPE decfloat34,
END OF json_subobject.
TYPES: BEGIN OF json_object,
a TYPE c LENGTH 10,
b TYPE json_subobject,
END OF json_object.
DATA: foo TYPE json_object.
DATA: lv_xmls TYPE string VALUE '{"a":"FooBar","b":{"c":9,"d":3.14}}',
lv_xmlb TYPE xstring.
TRY.
lv_xmlb = cl_abap_codepage=>convert_to(
source      = lv_xmls
codepage    = `UTF-8`
endian      = space
replacement = '#'
ignore_cerr = abap_false ).
CATCH cx_parameter_invalid_range cx_sy_codepage_converter_init cx_sy_conversion_codepage cx_parameter_invalid_type.
ENDTRY.
WRITE: |Deserializing JSON ...|.
NEW-LINE.
CALL TRANSFORMATION id SOURCE XML lv_xmlb RESULT XML = foo.
WRITE: '{'.
NEW-LINE.
WRITE: |  "a": "{ foo-a }",|.
NEW-LINE.
WRITE: |  "b": {|.
NEW-LINE.
WRITE: |    "c": { foo-b-c },|.
NEW-LINE.
WRITE: |    "d": { foo-b-d },|.
NEW-LINE.
WRITE: |  }|.
NEW-LINE.
WRITE: |}|.

我期望的输出是:

Deserializing JSON ...
{
"a":"FooBar",
"b":{
"c":9,
"d":3.14
}
}

但不幸的是,我得到的输出是:

Deserializing JSON ...
{
"a":"",
"b":{
"c":0,
"d":0
}
}

看起来CALL TRANSFORMATION语句对我没有任何作用。

有没有一位ABAP大师可以向我展示如何在这种(希望如此(简单的情况下使用CALL TRANSFORMATION?我已经环顾四周,发现这个有用的GitHub repo演示了如何将JSON反序列化为类,但为了简单起见,我更喜欢将JSON反格式化为结构。我不完全确定如何使用CALL TRANSFORMATION,因为我不熟悉XSLT和高级XML功能,所以如果可能的话,我非常感谢一个现成的解决方案。。。

提前感谢

约书亚

我的答案分为两部分。根据我的说法,第一部分是最适合JSON的解决方案,第二部分解释了为什么您的代码不能使用CALL TRANSFORMATION ID

第1部分:

您最好使用一个更适合处理JSON的SAP类。我更喜欢/UI2/CL_JSON类,这是我认为最"开放"的类,因为它是SAP最公开的类(请参阅以下文档(,尽管它没有得到官方支持(是的,这很难理解,欢迎来到SAP世界(。

TYPES: BEGIN OF json_subobject,
c TYPE i,
d TYPE decfloat34,
END OF json_subobject.
TYPES: BEGIN OF json_object,
a TYPE c LENGTH 10,
b TYPE json_subobject,
END OF json_object.
DATA: foo TYPE json_object.
/ui2/cl_json=>deserialize(
EXPORTING json = '{"a":"FooBar","b":{"c":9,"d":3.14}}'
CHANGING  data = foo ).
ASSERT foo = VALUE json_object( 
a   = 'FooBar' 
b-c = 9 
b-d = '3.14' ).

更多信息参考文件:

  • SCN上的Wiki,由SAP作者Alexey Arseniev撰写(或者,如果他不是原作者,他是维护该类的团队的一员(
  • 关于SCN的博客文章:在ABAP中解析JSON,作者Kerem Koseoglu,2017年8月3日

第2部分:

使用CALL TRANSFORMATION ID的代码无法工作有两个原因:

  1. JSON必须始终是一个JSON对象,其成员以根名称(RESULT rootname1 = var1 rootname2 = var2(命名。您只定义了一个名为"XML"的根,因此JSON应该类似于{"X-ML":...}(由于特定的ABAP原因,它是X-ML而不是XML(
  2. ABAP组件名称以大写字母(A、B、C、D(存储在SAP内部,身份转换ID与成员名称区分大小写,因此JSON数据的成员名称应以大写字母表示(您的所有名称都以小写字母A、B、C、D表示(

不同的是,如果您的输入JSON包含以下值,您的代码可能会工作:

lv_xmls = '{"X-ML":{"A":"FooBar","B":{"C":9,"D":3.14}}}'.

另一个解决方案可以是创建一个自定义身份转换,将JSON成员名称转换为大写,并添加一个伪根元素。但那是另一回事。

我不是一个优秀的ABAP开发人员,所以我不知道是否有更好的代码可以做到这一点,但这对我来说很有效:

TYPES: BEGIN OF json_subobject,
c TYPE i,
d TYPE decfloat34,
END OF json_subobject.
TYPES: BEGIN OF json_object,
a TYPE c LENGTH 10,
b TYPE json_subobject,
END OF json_object.
DATA: foo TYPE json_object,
writer TYPE REF TO cl_sxml_string_writer,
json TYPE xstring.
DATA: lv_xmls TYPE string VALUE '{"a":"FooBar","b":{"c":9,"d":3.14}}',
lv_xmlb TYPE xstring.
*TRY.
*    lv_xmlb = cl_abap_codepage=>convert_to(
*                source      = lv_xmls
*                codepage    = `UTF-8`
*                endian      = space
*                replacement = '#'
*                ignore_cerr = abap_false ).
*  CATCH cx_parameter_invalid_range cx_sy_codepage_converter_init cx_sy_conversion_codepage cx_parameter_invalid_type.
*    ENDTRY.

WRITE: |Deserializing JSON ...|.
NEW-LINE.
cl_fdt_json=>json_to_data( EXPORTING iv_json = lv_xmls
CHANGING ca_data = foo ).
WRITE: '{'.
NEW-LINE.
WRITE: |  "a": "{ foo-a }",|.
NEW-LINE.
WRITE: |  "b": {|.
NEW-LINE.
WRITE: |    "c": { foo-b-c },|.
NEW-LINE.
WRITE: |    "d": { foo-b-d },|.
NEW-LINE.
WRITE: |  }|.
NEW-LINE.
WRITE: |}|.

这段代码只是将JSON数组转换为一个内部表。

相关内容

  • 没有找到相关文章

最新更新