OpenX JSON SerDe
Hive JSON SerDe와 마찬가지로 OpenX JSON을 사용하여 JSON 데이터를 처리할 수 있습니다. 데이터는 새 줄로 구분된 JSON 인코딩 텍스트의 한 줄 문자열로도 표시됩니다. Hive JSON SerDe와 마찬가지로 OpenX JSON SerDe는 map
또는 struct
키 이름에 중복 키를 허용하지 않습니다.
고려 사항 및 제한
-
OpenX JSON SerDe를 사용하는 경우 결과의 수 및 값이 비결정적일 수 있습니다. 결과에는 예상보다 많거나 적은 수의 행 또는 기본 데이터에 없는 예상치 못한 null 값이 포함될 수 있습니다. 이 문제를 해결하려면 Hive JSON SerDe를 사용하거나 데이터를 다른 파일 형식으로 다시 쓰세요.
-
SerDe는 각 JSON 문서가 레코드의 필드를 구분하는 줄 종료 문자가 없는 한 줄의 텍스트에 있을 것으로 예상합니다. JSON 텍스트가 가독성 좋게 꾸민 형식이면 테이블을 만든 후 쿼리하려고 할 때
HIVE_CURSOR_ERROR: 행이 유효한 JSON 객체가 아님(HIVE_CURSOR_ERROR: Row is not a valid JSON Object)
또는HIVE_CURSOR_ERROR: JsonParseException: 예기치 않은 입력 종료: OBJECT의 닫기 마커 필요(HIVE_CURSOR_ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT)
같은 오류 메시지가 나타날 수 있습니다.자세한 내용은 GitHub의 OpenX SerDe 문서에서 JSON 데이터 파일
을 참조하세요.
선택적 속성
Hive JSON SerDe와 달리 OpenX JSON SerDe에는 데이터의 불일치를 해결하는 데 유용한 다음과 같은 선택적 SerDe 속성이 있습니다.
- ignore.malformed.json
-
선택 사항입니다.
TRUE
로 설정하면 형식이 잘못된 JSON 구문을 건너뛸 수 있습니다. 기본값은FALSE
입니다. - dots.in.keys
-
선택 사항입니다. 기본값은
FALSE
입니다.TRUE
로 설정하면 SerDe가 키 이름의 점을 밑줄로 바꿀 수 있습니다. 예를 들어 JSON 데이터 세트에 이름이"a.b"
인 키가 있을 경우 이 속성을 사용하여 Athena에서 열 이름이"a_b"
가 되도록 정의할 수 있습니다. 이 SerDe가 없으면 기본적으로 Athena는 열 이름에 점을 허용하지 않습니다. - case.insensitive
-
선택 사항입니다. 기본값은
TRUE
입니다.TRUE
로 설정하면 SerDe가 모든 대문자 열을 소문자로 변환합니다.데이터에서 대/소문자를 구분하는 키 이름을 사용하려면
WITH SERDEPROPERTIES ("case.insensitive"= FALSE;)
를 사용합니다. 그런 다음, 아직 모두 소문자가 아닌 모든 키에 대해 다음 구문을 사용하여 열 이름에서 속성 이름으로 매핑을 제공합니다.ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.userid" = "userId")
URL
및Url
와 같이 소문자로 동일한 두 개의 키가 있는 경우, 다음과 같은 오류가 발생할 수 있습니다.HIVE_CURSOR_ERROR: 행이 유효한 JSON 객체가 아님 - JSONException: 중복 키 "url"
이 문제를 해결하려면 다음 예제와 같이
case.insensitive
속성을FALSE
로 설정하고 키를 다른 이름으로 매핑합니다.ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.url1" = "URL", "mapping.url2" = "Url")
- 매핑
-
선택 사항입니다. 열 이름을, 열 이름과 동일하지 않은 JSON 키에 매핑합니다.
mapping
파라미터는 JSON 데이터에 키워드인 키가 있을 경우에 유용합니다. 예를 들어timestamp
라는 JSON 키가 있는 경우 다음 구문을 사용하여 키를ts
라는 열에 매핑합니다.ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("mapping.ts" = "timestamp")
Hive 호환 이름에 콜론이 있는 중첩된 필드 이름 매핑
struct
내에 콜론이 있는 필드 이름이 있는 경우mapping
속성을 사용하여 Hive 호환 이름에 필드를 매핑할 수 있습니다. 예를 들어 열 유형 정의에my:struct:field:string
이 포함된 경우WITH SERDEPROPERTIES
에 다음 항목을 포함하여my_struct_field:string
에 정의를 매핑할 수 있습니다.("mapping.my_struct_field" = "my:struct:field")
다음 예제에서는 해당
CREATE TABLE
문을 보여줍니다.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")
예제: 광고 데이터
다음 예제 DDL 문은 OpenX JSON SerDe를 사용하여 Hive JSON SerDe의 예제에 사용된 것과 동일한 샘플 온라인 광고 데이터를 기반으로 테이블을 생성합니다. LOCATION
절에서 myregion
을, 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';
예제: 중첩 JSON 역직렬화
JSON SerDes를 사용하여 더 복잡한 JSON 인코딩 데이터를 구문 분석 할 수 있습니다. 이를 위해서는 struct
및 array
요소를 사용하여 중첩 구조를 나타내는 CREATE TABLE
문을 사용해야 합니다.
다음 예제에서는 중첩 구조가 있는 JSON 데이터로 Athena 테이블을 생성합니다. 예제의 구조는 다음과 같습니다.
{
"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"
}
]
}
}
OpenX SerDe는 각 JSON 레코드가 한 줄의 텍스트에 있을 것으로 예상한다는 점을 기억하세요. Amazon S3에 저장되는 경우 이전 예제의 모든 데이터는 다음과 같이 한 줄에 있어야 합니다.
{"DocId":"AWS","User":{"Id":1234,"Username":"carlos_salazar","Name":"Carlos","ShippingAddress" ...
다음 CREATE TABLE
문은 Openx-JsonSerDestruct
및 array
컬렉션 데이터 형식을 사용하여 예제 데이터에 대한 객체 그룹을 설정합니다.
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
/';
테이블을 쿼리하려면 다음과 같은 간단한 SELECT
문을 사용합니다.
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)
샘플 쿼리는 구조체 내의 데이터 필드에 액세스하기 위해 점 표기법(예: user.name
)을 사용합니다. orders
필드와 마찬가지로 구조체 배열 내의 데이터에 액세스하려면 UNNEST
함수를 사용하면 됩니다. UNNEST
함수는 배열을 임시 테이블(이 경우 o
)로 평면화합니다. 이렇게 하면 구조체와 마찬가지로 점 표기법을 사용하여 중첩되지 않은 배열 요소에 액세스할 수 있습니다(예: o.itemid
). 예제에서 설명용으로 사용되는 temp_table
이름은 보통 t
와 같이 축약됩니다.
다음 표는 쿼리 결과를 보여 줍니다.
# | 명칭 | Address | 구/군/시 | Item_ID | Order_date |
---|---|---|---|---|---|
1 | Carlos | 123 Main St. | Anytown | 6789 | 2022/11/11 |
2 | Carlos | 123 Main St. | Anytown | 4352 | 2022/12/12 |