SerDe JSON OpenX
Comme le SerDE JSON Hive, vous pouvez utiliser le JSON OpenX pour traiter les données JSON. Les données sont également représentées sous forme de chaînes sur une ligne de texte codées en JSON et séparées par une nouvelle ligne. Comme le SerDe JSON Hive, le SerDe JSON OpenX n'autorise -pas les clés en double dans les noms de clé map ou struct.
Considérations et restrictions
-
Lorsque vous utilisez le SerDe JSON OpenX, le nombre de résultats et les valeurs associées peuvent être imprévisibles. Les résultats peuvent contenir plus ou moins de lignes que prévu ou encore des valeurs nulles alors que les données sous-jacentes n’en contiennent pas. Pour contourner ce problème, utilisez le SerDe JSON Hive ou réécrivez les données dans un autre type de format de fichier.
-
Le SerDe s'attend à ce que chaque document JSON soit sur une seule ligne de texte, sans caractères de fin de ligne pour séparer les champs de l'enregistrement. Si le texte JSON est au format d'impression, vous pouvez recevoir un message d'erreur similaire à
HIVE_CURSOR_ERROR : Row is not a valid JSON Object (La ligne n'est pas un JSON valide)ouHIVE_CURSOR_ERROR : JSONParseException : Unexpected end-of-input: expected close marker for OBJECT (Fin d'entrée inattendue : marqueur de fermeture attendu pour OBJECT)lorsque vous tentez d'interroger la table après l'avoir créée.Pour de plus amples informations, consultez la section Fichiers de données JSON
dans la documentation OpenX SerDe sur GitHub.
Propriétés facultatives
Contrairement au SerDe JSON Hive, le SerDe JSON OpenX possède également les propriétés SerDe facultatives suivantes qui peuvent être utiles pour résoudre les incohérences au niveau des données.
- use.null.for.invalid.data
-
Facultatif. La valeur par défaut est
FALSE. Lorsque cette propriété est définie surTRUE, le SerDe utiliseNULLpour les valeurs de colonne dont la désérialisation dans le type attendu par la colonne défini dans le schéma de table a échoué.Important
La définition de
use.null.for.invalid.datasurTRUEpeut entraîner des résultats incorrects ou inattendus, car les valeursNULLremplacent les données non valides dans les colonnes présentant des problèmes de correspondance de schéma. Il est préférable de corriger les données dans vos fichiers ou votre schéma de table que d’activer cette propriété. Lorsque vous activez cette propriété, les données non valides n’entraînent pas l’échec des requêtes, ce qui peut vous empêcher de déceler des problèmes de qualité des données. - ignore.malformed.json
-
Facultatif. Lorsque la valeur est définie sur
TRUE, cela vous permet d'ignorer la syntaxe JSON incorrecte. La valeur par défaut estFALSE. - dots.in.keys
-
Facultatif. La valeur par défaut est
FALSE. Lorsque la valeur est définieTRUE, permet au SerDe de remplacer les points dans les noms de clé par des traits de soulignement. Par exemple, si le jeu de données JSON contient une clé portant le nom"a.b", vous pouvez utiliser cette propriété pour définir le nom de la colonne comme étant"a_b"dans Athena. Par défaut (sans ce SerDe), Athena n'autorise pas les points dans les noms de colonnes. - case.insensitive
-
Facultatif. La valeur par défaut est
TRUE. Lorsque la valeur est définie surTRUE, le SerDe convertit toutes les majuscules des colonnes en minuscules.Pour utiliser des noms de clés sensibles à la casse dans vos données, utilisez
WITH SERDEPROPERTIES ("case.insensitive"= FALSE;). Ensuite, pour chaque clé qui n'est pas encore entièrement en minuscules, fournissez un mappage entre le nom de la colonne et le nom de la propriété à l'aide de la syntaxe suivante :ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.userid" = "userId")Si vous avez deux clés, comme
URLetUrl, qui sont identiques quand elles sont écrites en minuscules, une erreur comme celle-ci peut se produire :HIVE_CURSOR_ERROR: Row is not a valid JSON Object - JSONException: Duplicate key "url"Pour résoudre ce problème, définissez la propriété
case.insensitivesurFALSEet mapper les clés avec différents noms, comme dans l'exemple suivant :ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.url1" = "URL", "mapping.url2" = "Url") - mappage
-
Facultatif. Cette propriété mappe les noms de colonnes aux clés JSON qui ne sont pas identiques aux noms de colonne. Le paramètre
mappingest utile lorsque les données JSON contiennent des clés qui sont des mots-clés. Par exemple, si vous avez une clé JSON nomméetimestamp, utilisez la syntaxe suivante pour mapper la clé à une colonne nomméets:ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("mapping.ts" = "timestamp")Mapper les noms de champs imbriqués avec des deux-points à des noms compatibles avec Hive
Si vous avez un nom de champ avec des deux-points à l’intérieur d’un
struct, vous pouvez utiliser la propriétémappingpour associer le champ à un nom compatible avec Hive. Par exemple, si vos définitions de type de colonne contiennentmy:struct:field:string, vous pouvez mapper la définition àmy_struct_field:stringen incluant l’entrée suivante dansWITH SERDEPROPERTIES:("mapping.my_struct_field" = "my:struct:field")L’exemple suivant montre l’instruction
CREATE TABLEcorrespondante.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")
Exemple : données publicitaires
L'exemple d'instruction DDL suivant utilise le SerDe JSON OpenX pour créer une table basée sur le même exemple de données publicitaires en ligne utilisé dans l'exemple du SerDe JSON Hive. Dans la clause LOCATION, remplacez myregion par l'identifiant de la région dans laquelle vous exécutez 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';
Exemple : désérialisation des données JSON imbriquées
Vous pouvez utiliser les SerDe JSON pour analyser des données codées en JSON plus complexes. Cela implique l'utilisation d'instructions CREATE TABLE utilisant des éléments struct et array pour représenter des structures imbriquées.
L'exemple suivant crée une table Athena à partir de données JSON ayant des structures imbriquées. Il présente la structure suivante :
{
"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"
}
]
}
}
N’oubliez pas que le SerDe OpenX s’attend à ce que chaque enregistrement JSON se trouve sur une ligne de texte distincte. Lorsqu’elles sont stockées dans Amazon S3, toutes les données de l’exemple précédent doivent figurer sur une seule ligne, comme illustré ci-dessous :
{"DocId":"AWS","User":{"Id":1234,"Username":"carlos_salazar","Name":"Carlos","ShippingAddress" ...
L’instruction CREATE TABLE suivante utilise le SerDe Openx-JsonSerDestruct et array pour établir des groupes d’objets pour les données de l’exemple.
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/';
Utilisez une instruction SELECT semblable à la suivante pour interroger la table :
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)
Pour accéder aux champs de données des structures, la requête de l’exemple utilise la notation par points (par exemple, user.name). Vous pouvez utiliser la fonction UNNEST pour accéder aux données d’un tableau de structures (comme pour le champ orders). La fonction UNNEST aplatit le tableau en table temporaire (appelée o dans ce cas). Vous pouvez ainsi utiliser la notation par points comme vous le feriez avec les structures pour accéder aux éléments de tableau non imbriqués (par exemple, o.itemid). Le nom temp_table, utilisé dans l’exemple à des fins d’illustration, est souvent abrégé en t.
Le tableau ci-dessous présente les résultats de la requête.
| # | Nom | Address | Ville | Item_ID | Order_date |
|---|---|---|---|---|---|
| 1 | Carlos | 123 Main St. | Anytown | 6789 | 11/11/2022 |
| 2 | Carlos | 123 Main St. | Anytown | 4352 | 12/12/2022 |