Necesito convertir un string de formato JSON a tabla interna, encontré que con la clase CL_TREX_JSON_DESERIALIZER lo puedo hacer, pero tengo un error, este cuando solo admite que los valores estén encerrados en comillas dobles, por lo que me genera problema ya que el formato JSON pone el formato de columna con comillas dobles también. A continuación, un ejemplo de los archivos JSON:
Buenos días @alejovelas,
encontré por ahí buscando una clase Z que lo hace y me funciona bien.
Te paso el método:
JSON TO DATA
Parámetros:
JSON TYPE STRING (IMPORTING)
DATA TYPE ANY (CHANGING)
METHOD JSON_TO_DATA.
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.
JSON_TO_DATA( EXPORTING JSON = LV_VALUE CHANGING DATA = <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.
JSON_TO_DATA( EXPORTING JSON = LV_KEY CHANGING DATA = <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.
ENDMETHOD. "json_to_data
Lo único que me parece que hay que controlar es que el string no sea “[ ]”.
Muchas gracias @Salco me parece que me será de mucha ayuda.
No tengo mucho conocimiento sobre abap POO, me puedes ayudar con un error que me muestra al hacer el llamado del método, me da el siguiente mensaje:
Al parámetro obligatorio “DATA” no se le han proporcionado datos
la forma en que lo llamo es la siguiente:
TYPES: BEGIN OF ty_respuesta,
code(2) TYPE c,
status(2) TYPE c,
data TYPE string,
fecha(25) TYPE c,
emisor TYPE ty_emisor,
receptor TYPE ty_receptor,
clave(50) TYPE c,
hacienda_status(2) TYPE c,
hacienda_mensaje TYPE string,
END OF ty_respuesta.
DATA: wa_respuesta TYPE ty_respuesta.
DATA lr_json_ds TYPE REF TO ZCL_TREX_JSON_SERIALIZER.