我想将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?我已经环顾四周,发现this helpful GitHub repo演示了如何将JSON反序列化为一个类,但是为了简单起见,我更喜欢将JSON反序列化为一个结构。我不太确定如何使用CALL TRANSFORMATION,因为我不熟悉XSLT和高级XML功能,因此,如果可能的话,我非常感谢现有的解决方案...
非常感谢
约书亚
答案 0 :(得分:4)
我的回答分为两个部分。据我介绍,第一个是最适合JSON的解决方案,第二个部分说明了为什么您的代码无法与CALL TRANSFORMATION ID
一起使用。
PART 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' ).
参考文档以获取更多信息:
PART 2:
您的CALL TRANSFORMATION ID
代码无法正常工作有两个原因:
RESULT rootname1 = var1 rootname2 = var2
)命名的成员的JSON对象。您仅定义了一个名为“ XML”的根,所以JSON应该类似于{"X-ML":...}
(由于特定的ABAP reason,它的名称为X-ML
,而不是XML
)ID
关于成员名称区分大小写,因此JSON数据的成员名称应大写(您的所有名称都用小写的a,b,c,d)。不同地说,如果您输入的JSON包含以下值,您的代码可能会起作用:
lv_xmls = '{"X-ML":{"A":"FooBar","B":{"C":9,"D":3.14}}}'.
另一种解决方案可以包括创建一个自定义身份转换,该转换将JSON成员名称转换为大写并添加一个虚拟根元素。但这是另一个故事。
答案 1 :(得分:1)
我不是一个优秀的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数组转换为内部表。