

# Bibliotecas de SerDe JSON
<a name="json-serde"></a>

En Athena, puede utilizar dos bibliotecas SerDe para deserializar datos JSON. La deserialización convierte los datos JSON para que se puedan serializar (escribir) en un formato diferente como Parquet u ORC.
+ [El SerDe JSON de Hive](hive-json-serde.md)
+ [El SerDe JSON de OpenX](openx-json-serde.md) 
+ [SerDe de Amazon Ion Hive](ion-serde.md)

**nota**  
Las bibliotecas de Hive y OpenX esperan que los datos JSON estén en una sola línea (sin formato), con registros separados por un carácter de nueva línea.

Dado que Amazon Ion es un superconjunto de JSON, puede utilizar el SerDe de Amazon Ion Hive para consultar conjuntos de datos JSON que no sean de Amazon Ion. A diferencia de otras bibliotecas de SerDe JSON de OpenX y Hive, el SerDe de Amazon Ion no espera que cada fila de datos esté en una sola línea. Esta característica resulta útil si desea consultar conjuntos de datos JSON que presentan “un buen formato de impresión” o dividir los campos en una fila con caracteres de nueva línea.

## Nombres de las bibliotecas
<a name="library-names"></a>

Utilice una de las siguientes:

 [org.apache.hive.hcatalog.data.JsonSerDe](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-JSON) 

 [org.openx.data.jsonserde.JsonSerDe](https://github.com/rcongiu/Hive-JSON-Serde) 

[com.amazon.ionhiveserde.IonHiveSerDe](https://github.com/amzn/ion-hive-serde)

# El SerDe JSON de Hive
<a name="hive-json-serde"></a>

SerDe JSON de Hive se usa normalmente para procesar datos JSON como eventos. Estos eventos se representan como cadenas de una sola línea de texto con codificación JSON separados por una línea nueva. SerDe JSON de Hive no permite claves duplicadas en `map` ni nombres de claves `struct`.

**nota**  
El SerDe espera que cada documento JSON esté en una sola línea de texto sin caracteres de terminación de línea que separen los campos del registro. Si el texto JSON está en formato de impresión, puede recibir un mensaje de error como HIVE\$1CURSOR\$1ERROR: la fila no es un objeto JSON válido o HIVE\$1CURSOR\$1ERROR: JsonParseException: fin de entrada inesperado: marcador de cierre esperado para OBJECT cuando intenta consultar la tabla después de crearla. Para obtener más información, consulte los [Archivos de datos JSON](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files) en la documentación de OpenX SerDE en GitHub. 

La instrucción DDL de ejemplo que se muestra a continuación, utiliza SerDe JSON de Hive para crear una tabla en función de los datos de publicidad en línea de ejemplo. En la cláusula `LOCATION`, reemplace *myregion* en `s3://amzn-s3-demo-bucket.elasticmapreduce/samples/hive-ads/tables/impressions` por el identificador de región donde se ejecuta Athena (por ejemplo, `s3://us-west-2.elasticmapreduce/samples/hive-ads/tables/impressions`).

```
CREATE EXTERNAL TABLE impressions (
    requestbegintime string,
    adid string,
    impressionid string,
    referrer string,
    useragent string,
    usercookie string,
    ip string,
    number string,
    processid string,
    browsercookie string,
    requestendtime string,
    timers struct
                <
                 modellookup:string, 
                 requesttime:string
                >,
    threadid string, 
    hostname string,
    sessionid string
)   
PARTITIONED BY (dt string)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://amzn-s3-demo-bucket.elasticmapreduce/samples/hive-ads/tables/impressions';
```

## Especificación de formatos de marca de tiempo con SerDe JSON de Hive
<a name="hive-json-serde-timestamp-formats"></a>

Para analizar los valores de marca de tiempo de una cadena, se puede agregar el subcampo `WITH SERDEPROPERTIES` a la cláusula `ROW FORMAT SERDE` y utilizarla para especificar el parámetro `timestamp.formats`. En el parámetro, se debe especificar una lista separada por comas de uno o más patrones de marca de tiempo, como en el siguiente ejemplo:

```
...
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
WITH SERDEPROPERTIES ("timestamp.formats"="yyyy-MM-dd'T'HH:mm:ss.SSS'Z',yyyy-MM-dd'T'HH:mm:ss")
...
```

Para obtener más información, consulte [Timestamps](https://cwiki.apache.org/confluence/display/hive/languagemanual+types#LanguageManualTypes-TimestampstimestampTimestamps) en la documentación de Apache Hive.

## Carga de la tabla para consultas
<a name="hive-json-serde-loading-the-table"></a>

Después de crear la tabla, ejecute [MSCK REPAIR TABLE](msck-repair-table.md) para cargar la tabla y hacerla consultable desde Athena:

```
MSCK REPAIR TABLE impressions
```

## Consulta de registros de CloudTrail
<a name="hive-json-serde-querying-cloud-trail-logs"></a>

Puede usar los SerDe JSON de Hive para consultar los registros de CloudTrail. Para obtener más información y ejemplos de las instrucciones `CREATE TABLE`, consulte [Consulta de registros de AWS CloudTrail](cloudtrail-logs.md).

# El SerDe JSON de OpenX
<a name="openx-json-serde"></a>

Al igual que el SerDe JSON de Hive, puede utilizar el JSON de OpenX para procesar datos JSON. Los datos también se representan como cadenas de una sola línea de texto con codificación JSON separadas por una línea nueva. Al igual que SerDe JSON de Hive, SerDe JSON de OpenX no permite claves duplicadas en `map` ni nombres de claves `struct`. 

## Consideraciones y limitaciones
<a name="openx-json-serde-considerations-limitations"></a>
+ Al utilizar el OpenX JSON SerDe, el número de resultados y sus valores pueden ser no deterministas. Los resultados pueden contener más filas de las esperadas, menos filas de las esperadas o valores nulos inesperados cuando no hay ninguno en los datos subyacentes. Para solucionar este problema, utilice [El SerDe JSON de Hive](hive-json-serde.md) o vuelva a escribir los datos en otro tipo de formato de archivo.
+ El SerDe espera que cada documento JSON esté en una sola línea de texto sin caracteres de terminación de línea que separen los campos del registro. Si el texto JSON está en formato de impresión, puede recibir un mensaje de error como HIVE\$1CURSOR\$1ERROR: la fila no es un objeto JSON válido o HIVE\$1CURSOR\$1ERROR: JsonParseException: fin de entrada inesperado: marcador de cierre esperado para OBJECT cuando intenta consultar la tabla después de crearla. 

  Para obtener más información, consulte los [Archivos de datos JSON](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files) en la documentación de OpenX SerDE en GitHub. 

## Propiedades opcionales
<a name="openx-json-serde-optional-properties"></a>

A diferencia del SerDe JSON de Hive, el SerDe JSON de OpenX también tiene las siguientes propiedades SerDe opcionales que pueden resultar útiles para solucionar incoherencias en los datos.

**use.null.for.invalid.data**  
Opcional. El valor predeterminado es `FALSE`. Cuando se establece en `TRUE`, SerDe utiliza `NULL` para los valores de columna que no se han podido deserializar en el tipo de columna definido en el esquema de la tabla.  
Establecer `use.null.for.invalid.data` en `TRUE` puede provocar resultados incorrectos o inesperados, ya que los valores `NULL` sustituyen los datos que no son válidos en columnas con incompatibilidades de esquema. Recomendamos que corrija los datos en los archivos o en el esquema de la tabla en lugar de habilitar esta propiedad. Si habilita esta propiedad, no se producirán errores en las consultas con datos que no sean válidos, lo que podría impedirle detectar problemas relacionados con la calidad de los datos.

**ignore.malformed.json**  
Opcional. Cuando se establece en `TRUE`, le permite omitir la sintaxis JSON con formato incorrecto. El valor predeterminado es `FALSE`.

**dots.in.keys**  
Opcional. El valor predeterminado es `FALSE`. Cuando se establece en `TRUE`, permite que el SerDe sustituya los puntos en nombres de claves con guiones bajos. Por ejemplo, si el conjunto de datos de JSON contiene una clave con el nombre `"a.b"`, puede utilizar esta propiedad para definir el nombre de la columna para que sea `"a_b"` en Athena. De forma predeterminada (sin este SerDe), Athena no permite puntos en los nombres de columnas.

**case.insensitive**  
Opcional. El valor predeterminado es `TRUE`. Cuando se establece en `TRUE`, el SerDe convierte todas las columnas en mayúscula a minúscula.   
Para utilizar nombres de clave que distinguen mayúsculas de minúsculas en los datos, utilice `WITH SERDEPROPERTIES ("case.insensitive"= FALSE;)`. A continuación, para cada clave que no esté ya en minúsculas, proporcione un mapeo desde el nombre de la columna al nombre de la propiedad utilizando la siguiente sintaxis:  

```
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.userid" = "userId")
```
Si tiene dos claves como `URL` y `Url` que son iguales cuando se escriben en minúsculas, puede producirse un error como el siguiente:  
HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object - JSONException: Duplicate key "url"  
Para resolver esto, establezca la propiedad `case.insensitive` en `FALSE` y asigne las claves a nombres diferentes, como en el ejemplo siguiente:  

```
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.url1" = "URL", "mapping.url2" = "Url")
```

**asignación**  
Opcional. Asigna nombres de columna a las claves JSON que no son idénticas a los nombres de las columnas. El parámetro `mapping` es útil cuando los datos JSON contienen claves que son [palabras clave](reserved-words.md). Por ejemplo, si tiene una clave JSON denominada `timestamp`, utilice la siguiente sintaxis para mapear la clave a una columna denominada `ts`:  

```
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES ("mapping.ts" = "timestamp")
```
**Asignación de nombres de campos anidados con dos puntos a nombres compatibles con Hive**  
Si tiene un nombre de campo con dos puntos dentro de una estructura `struct`, puede utilizar la propiedad `mapping` para asignar ese campo a un nombre compatible con Hive. Por ejemplo, si las definiciones de tipos de columna contienen `my:struct:field:string`, puede asignar la definición a `my_struct_field:string` incluyendo la siguiente entrada en `WITH SERDEPROPERTIES`:

```
("mapping.my_struct_field" = "my:struct:field")
```
En el siguiente ejemplo se muestra la instrucción `CREATE TABLE` correspondiente.  

```
CREATE EXTERNAL TABLE colon_nested_field (
item struct<my_struct_field:string>)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES ("mapping.my_struct_field" = "my:struct:field")
```

## Ejemplo: datos de publicidad
<a name="openx-json-serde-ad-data-example"></a>

La instrucción DDL de ejemplo que se muestra a continuación, utiliza SerDe JSON de OpenX para crear una tabla en función de los mismos datos de publicidad en línea de ejemplo utilizados en el ejemplo para SerDe JSON de Hive. En la cláusula `LOCATION`, reemplace *myregion* por el identificador de región donde se ejecuta Athena.

```
CREATE EXTERNAL TABLE impressions (
    requestbegintime string,
    adid string,
    impressionId string,
    referrer string,
    useragent string,
    usercookie string,
    ip string,
    number string,
    processid string,
    browsercokie string,
    requestendtime string,
    timers struct<
       modellookup:string, 
       requesttime:string>,
    threadid string, 
    hostname string,
    sessionid string
)   PARTITIONED BY (dt string)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://amzn-s3-demo-bucket.elasticmapreduce/samples/hive-ads/tables/impressions';
```

## Ejemplo: deserialización de JSON anidado
<a name="nested-json-serde-example"></a>

Puede usar SerDes JSON para analizar datos codificados en JSON más complejos. Esto requiere el uso de instrucciones `CREATE TABLE` que utilizan elementos `struct` y `array` para representar estructuras anidadas. 

En el ejemplo siguiente, se crea una tabla de Athena a partir de datos JSON que tienen estructuras anidadas. El ejemplo tiene la siguiente estructura:

```
{
"DocId": "AWS",
"User": {
        "Id": 1234,
        "Username": "carlos_salazar", 
        "Name": "Carlos",
"ShippingAddress": {
"Address1": "123 Main St.",
"Address2": null,
"City": "Anytown",
"State": "CA"
   },
"Orders": [
   {
     "ItemId": 6789,
     "OrderDate": "11/11/2022" 
   },
   {
     "ItemId": 4352,
     "OrderDate": "12/12/2022"
   }
  ]
 }
}
```

Recuerde que OpenX SerDe espera que cada registro JSON esté en una sola línea de texto. Cuando se almacenan en Amazon S3, todos los datos del ejemplo anterior deben estar en una sola línea, así:

```
{"DocId":"AWS","User":{"Id":1234,"Username":"carlos_salazar","Name":"Carlos","ShippingAddress" ...
```

La siguiente instrucción `CREATE TABLE` utiliza [Openx-JsonSerDe](https://github.com/rcongiu/Hive-JSON-Serde) con los tipos de datos de recopilación `struct` y `array` para establecer grupos de objetos para los datos de ejemplo. 

```
CREATE external TABLE complex_json (
   docid string,
   `user` struct<
               id:INT,
               username:string,
               name:string,
               shippingaddress:struct<
                                      address1:string,
                                      address2:string,
                                      city:string,
                                      state:string
                                      >,
               orders:array<
                            struct<
                                 itemid:INT,
                                  orderdate:string
                                  >
                              >
               >
   )
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://amzn-s3-demo-bucket/myjsondata/';
```

Para consultar la tabla, utilice una instrucción `SELECT` como la siguiente.

```
SELECT 
 user.name as Name, 
 user.shippingaddress.address1 as Address, 
 user.shippingaddress.city as City, 
 o.itemid as Item_ID, o.orderdate as Order_date
FROM complex_json, UNNEST(user.orders) as temp_table (o)
```

Para acceder a los campos de datos dentro de las estructuras tipo struct, la consulta de ejemplo utiliza la notación con puntos (por ejemplo, `user.name`). Para acceder a los datos dentro de una matriz de estructuras tipo struct (como con el campo `orders`), puede utilizar la función `UNNEST`. La función `UNNEST` aplana la matriz en una tabla temporal (en este caso llamada `o`). Esto permite utilizar la notación de puntos como se hace con las estructuras tipo structs para acceder a los elementos no anidados de la matriz (por ejemplo, `o.itemid`). El nombre `temp_table`, utilizado en el ejemplo con fines ilustrativos, normalmente se abrevia como `t`.

La siguiente tabla muestra los resultados de la consulta.


****  

| \$1 | Nombre | Dirección | Ciudad | Item\$1ID | Order\$1date | 
| --- | --- | --- | --- | --- | --- | 
| 1 | Carlos | 123 Main St. | Anytown | 6789 | 11/11/2022 | 
| 2 | Carlos | 123 Main St. | Anytown | 4352 | 12/12/2022 | 

## Recursos adicionales de
<a name="json-serdes-additional-resources"></a>

Para obtener más información sobre cómo trabajar con JSON y JSON anidado en Athena, consulte los siguientes recursos:
+ [Crear tablas en Amazon Athena a partir de JSON anidado y asignaciones por medio de JSONSerDe](https://aws.amazon.com/blogs/big-data/create-tables-in-amazon-athena-from-nested-json-and-mappings-using-jsonserde/) (Blog de macrodatos en AWS)
+ [Recibo errores cuando intento leer datos JSON en Amazon Athena](https://aws.amazon.com/premiumsupport/knowledge-center/error-json-athena/) (artículo del centro de conocimiento de AWS)
+ [hive-json-schema](https://github.com/quux00/hive-json-schema) (GitHub): herramienta escrita en Java que genera instrucciones `CREATE TABLE` de documentos JSON de ejemplo. Las instrucciones `CREATE TABLE` que se generan utilizan SerDe JSON de OpenX.