Convertir JSON a tabla interna

Hola consultores!

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:

Formato correocto
{
“code”: 1,
“status”: “200”,
“data”: “PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGlumljYSB4bWxucz0iaHR0cHM6Ly90c”,
“fecha”: “2018-08-31T08:24:25-06:00”,
“emisor”: {
“tipoIdentificacion”: “02”,
“numeroIdentificacion”: “3101428097”
},
“receptor”: {
“tipoIdentificacion”: “02”,
“numeroIdentificacion”: “3101123456”
},
“clave”: "506270818003101000000002146067822 ",
"Hacienda_status ": “1”,
"hacienda_mensaje ": "https:XXXX "
}

Formato que admite la clase CL_TREX_JSON_DESERIALIZER
{
code: 1,
status: “200”,
data: “PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGlumljYSB4bWxucz0iaHR0cHM6Ly90c”,
fecha: “2018-08-31T08:24:25-06:00”,
emisor: {
TipoIdentificacion: “02”,
numeroIdentificacion: “3101428097”
},
receptor: {
tipoIdentificacion: “02”,
numeroIdentificacion: “3101123456”
},
clave: "506270818003101000000002146067822 ",
Hacienda_status : “1”,
hacienda_mensaje: "https:XXXX "
}

Alguien me puede ayudar a solventar este problema o conoce otra manera de convertir un formato JSON a ITAB.

Gracias de antemano!

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 “[ ]”.

2 Me gusta

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.
CREATE OBJECT lr_json_ds.
lr_json_ds->JSON_TO_DATA(
       IMPORTING
          json  = vs_json
       CHANGING 
          data  = wa_respuesta ).

Yo se que ha de ser por algo sencillo pero lo desconozco. Muy agradecido de antemano.

Volví el método Estático y lo llamo de esta forma y ya no tuve inconveniente.

CALL METHOD ZCL_TREX_JSON_SERIALIZER=>JSON_TO_DATA(
  EXPORTING
    JSON  = VS_JSON
  CHANGING
    DATA  = WA_RESPUESTA ).

Muchas gracias por el apoyo, si pudieras responder porqué no pude de la otra forma te lo agradeceré para tomarlo en cuenta.

El tipo de parámetro de la variable json debería ser “EXPORTING” en lugar de importing.

1 me gusta

Este tema se cerró automáticamente 7 días después del último post. No se permiten nuevas respuestas.