Created
April 2, 2012 09:26
-
-
Save mydoghasworms/2282070 to your computer and use it in GitHub Desktop.
Very trusting JSON to (deep) ABAP data structure mapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*&---------------------------------------------------------------------* | |
*& Form json_to_data | |
*&---------------------------------------------------------------------* | |
form json_to_data using json type string changing data type any. | |
data: lv_off type i. | |
data: lv_len type i. | |
data: lv_key type string. | |
data: lv_value type string. | |
data: lv_char type char1. "Current chacater | |
data: lv_pchar type char1. "Previous character | |
data: lv_instr type boole_d. "Indicator: cursor in string | |
data: lv_level type i. "Depth inside a block | |
data: lv_table type boole_d. | |
field-symbols: <fk> type string. | |
field-symbols: <data> type any. | |
field-symbols: <table> type any table. | |
field-symbols: <sotab> type sorted table. | |
field-symbols: <sttab> type standard table. | |
field-symbols: <line> type any. | |
data: ls_line type ref to data. | |
data: lr_td type ref to cl_abap_typedescr. | |
data: lr_ttd type ref to cl_abap_tabledescr. | |
* If the incoming json contains no '{}[]', we are dealing with | |
* a basic (scalar) value that is simply assigned to the data | |
* and then we return | |
if json na '{}[]'. | |
* Replace escape characters (TODO: Check if there are more!) | |
lv_value = json. | |
replace all occurrences of '\n' in lv_value with cl_abap_char_utilities=>newline. | |
replace all occurrences of '\t' in lv_value with cl_abap_char_utilities=>horizontal_tab. | |
replace all occurrences of '\f' in lv_value with cl_abap_char_utilities=>form_feed. | |
replace all occurrences of '\v' in lv_value with cl_abap_char_utilities=>vertical_tab. | |
replace all occurrences of '\b' in lv_value with cl_abap_char_utilities=>backspace. | |
replace all occurrences of '\\' in lv_value with '\'. | |
* TODO: Deal with specific data types, e.g. dates etc. | |
data = lv_value. | |
exit. | |
endif. | |
lv_len = strlen( json ). | |
* Check if we are dealing with a table | |
lr_td = cl_abap_typedescr=>describe_by_data( data ). | |
if lr_td->type_kind = cl_abap_typedescr=>typekind_table. | |
* This information is used later... | |
lv_table = 'X'. | |
assign data to <table>. | |
create data ls_line like line of <table>. | |
assign ls_line->* to <line>. | |
else. | |
lv_table = ' '. | |
endif. | |
* Reset counters/flags | |
lv_off = 0. | |
lv_instr = ' '. | |
lv_level = 0. | |
assign lv_key to <fk>. | |
while lv_off < lv_len. | |
lv_char = json+lv_off(1). | |
********************************************************************** | |
* IN STRING | |
********************************************************************** | |
* Character is in a string delimited by double quotes | |
if lv_instr = 'X'. | |
if lv_char = '"'. | |
* Switch out of delimited character string | |
if lv_pchar ne '\'. | |
lv_instr = ' '. | |
else. | |
concatenate <fk> lv_char into <fk> respecting blanks. | |
endif. | |
else. | |
concatenate <fk> lv_char into <fk> respecting blanks. | |
endif. | |
********************************************************************** | |
* OUTSIDE STRING | |
********************************************************************** | |
* Character is not in a string delimited by double quotes | |
else. | |
* On opening character, shift level up | |
if lv_char ca '{['. | |
add 1 to lv_level. | |
endif. | |
* When the value is contained in a {}/[], the entire value must | |
* be passed to the next level of processing | |
if lv_level > 1. | |
concatenate <fk> lv_char into <fk> respecting blanks. | |
else. | |
if lv_char ca '[{'. "<- Chars ignored outside of str | |
elseif lv_char = ':'. | |
assign lv_value to <fk>. | |
* The key collected up to now is assigned to the data member | |
translate lv_key to upper case. | |
shift lv_key left deleting leading space. | |
assign component lv_key of structure data to <data>. | |
* End of a key/value pair (we bump up against delimiter) - pass to next level | |
elseif ( lv_char = ',' or lv_char = '}' ) and lv_table = space. | |
* Process collected value | |
shift lv_value left deleting leading space. | |
perform json_to_data using lv_value changing <data>. | |
* Clear key and value | |
clear: lv_key, lv_value. | |
assign lv_key to <fk>. | |
clear: lv_key, lv_value. | |
* End of a key/value pair (we bump up against delimiter) - pass to next level | |
* But in table mode, we pass an instance of a row of the table, and afterward | |
* add it to the table | |
elseif ( lv_char = ',' or lv_char = ']' ) and lv_table = 'X'. | |
* Process collected value | |
* Inside array in JSON, there are no keys, only list of values, the collected | |
* value is in lv_key | |
shift lv_key left deleting leading space. | |
perform json_to_data using lv_key changing <line>. | |
* On return: if dealing with table, add the record to the table | |
lr_ttd ?= lr_td. | |
if lr_ttd->table_kind = cl_abap_tabledescr=>tablekind_sorted | |
or lr_ttd->table_kind = cl_abap_tabledescr=>tablekind_hashed. | |
assign data to <sotab>. | |
insert <line> into table <sotab>. | |
else. | |
assign data to <sttab>. | |
append <line> to <sttab>. | |
endif. | |
clear <line>. | |
* Clear key and value | |
clear: lv_key, lv_value. | |
assign lv_key to <fk>. | |
clear: lv_key, lv_value. | |
* Switch cursor into delimited string; consecutive characters | |
* are then treated as part of a key or value, even if they are | |
* special characters | |
elseif lv_char = '"'. | |
lv_instr = 'X'. | |
* Other chars processed as either key or value | |
else. | |
concatenate <fk> lv_char into <fk> respecting blanks. | |
endif. | |
endif. | |
* On closing character, shift level down again | |
if lv_char ca '}]'. | |
subtract 1 from lv_level. | |
endif. | |
* END: Are we in string or out? | |
endif. | |
lv_pchar = lv_char. | |
add 1 to lv_off. | |
endwhile. | |
endform. "json_to_data |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello, how to hand with as normal Json-File. It doesn't work in this case.
{
"results" : [
{
"address_components" : [
{
"long_name" : "Subotica",
"short_name" : "SU",
"types" : [ "locality", "political" ]
},
{
"long_name" : "North Bačka District",
"short_name" : "North Bačka District",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "Vojvodina",
"short_name" : "Vojvodina",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "Serbia",
"short_name" : "RS",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "Subotica, Serbia",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 46.1897987,
"lng" : 19.7770429
},
"southwest" : {
"lat" : 45.9975281,
"lng" : 19.5711994
}
},
"location" : {
"lat" : 46.098209,
"lng" : 19.67111
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 46.1897987,
"lng" : 19.7770429
},
"southwest" : {
"lat" : 45.9975281,
"lng" : 19.5711994
}
}
},
"types" : [ "locality", "political" ]
}
],
"status" : "OK"
}