JSON 로딩
JSON 로딩 (Loading JSON)
DuckDB의 JSON 리더는 JSON 파일을 분석해서 어떤 설정 플래그를 써야 할지 스스로 추론합니다. 대부분의 상황에서 이 방식이 잘 동작하므로, 가장 먼저 시도해보는 것이 좋습니다. 드물게 JSON 리더가 올바른 설정을 알아내지 못하는 상황에서는, 설정을 직접 지정해서 JSON 파일을 올바르게 파싱할 수 있습니다.
출처: 공식문서
read_json 함수
read_json은 JSON 파일을 로딩하는 가장 간단한 방법입니다. JSON 리더의 올바른 설정을 자동으로 알아내려고 시도하고, 컬럼의 타입도 자동으로 추론합니다. 아래 예제에서는 todos.json 파일을 사용합니다.
SELECT *
FROM read_json('todos.json')
LIMIT 5;
| userId | id | title | completed |
|---|---|---|---|
| 1 | 1 | delectus aut autem | false |
| 1 | 2 | quis ut nam facilis et officia qui | false |
| 1 | 3 | fugiat veniam minus | false |
| 1 | 4 | et porro tempora | true |
| 1 | 5 | laboriosam mollitia et enim quasi adipisci quia provident illum | false |
read_json을 사용해 영구 테이블을 만들 수도 있습니다.
CREATE TABLE todos AS
SELECT *
FROM read_json('todos.json');
DESCRIBE todos;
| column_name | column_type | null | key | default | extra |
|---|---|---|---|---|---|
| userId | UBIGINT | YES | NULL | NULL | NULL |
| id | UBIGINT | YES | NULL | NULL | NULL |
| title | VARCHAR | YES | NULL | NULL | NULL |
| completed | BOOLEAN | YES | NULL | NULL | NULL |
일부 컬럼에 대해서만 타입을 지정하면, read_json은 지정하지 않은 컬럼을 제외합니다.
SELECT *
FROM read_json(
'todos.json',
columns = {userId: 'UBIGINT', completed: 'BOOLEAN'}
)
LIMIT 5;
userId와 completed 컬럼만 표시되는 점을 확인하세요.
| userId | completed |
|---|---|
| 1 | false |
| 1 | false |
| 1 | false |
| 1 | true |
| 1 | false |
여러 파일을 한 번에 읽으려면 glob 패턴이나 파일 목록을 제공하면 됩니다. 자세한 내용은 multiple files 섹션을 참고하세요.
JSON 객체를 읽는 함수 (Functions for Reading JSON Objects)
JSON을 읽는 데 사용되는 테이블 함수는 다음과 같습니다.
| Function | Description |
|---|---|
| read_json_objects(filename) | filename에서 JSON 객체 하나를 읽습니다. filename은 파일 목록이나 glob 패턴일 수도 있습니다. |
| read_ndjson_objects(filename) | format 파라미터를 newline_delimited로 설정한 read_json_objects의 별칭. |
| read_json_objects_auto(filename) | format 파라미터를 auto로 설정한 read_json_objects의 별칭. |
파라미터 (Parameters)
이 함수들의 파라미터는 다음과 같습니다.
| Name | Description | Type | Default |
|---|---|---|---|
| compression | 파일의 압축 타입. 기본적으로 파일 확장자에서 자동 감지됩니다(예: t.json.gz는 gzip, t.json은 none). 옵션은 none, gzip, zstd, auto_detect. |
VARCHAR | auto_detect |
| filename | 결과에 추가 filename 컬럼을 포함할지 여부. DuckDB v1.3.0부터 filename 컬럼은 가상 컬럼으로 자동 추가되어, 이 옵션은 호환성 목적으로만 유지됩니다. | BOOL | false |
| format | auto, unstructured, newline_delimited, array 중 하나. | VARCHAR | array |
| hive_partitioning | 경로를 Hive 파티셔닝으로 해석할지 여부. | BOOL | (auto-detected) |
| ignore_errors | 파싱 오류를 무시할지 여부(format이 newline_delimited일 때만 가능). | BOOL | false |
| maximum_sample_files | 자동 감지를 위해 샘플링할 최대 JSON 파일 수. | BIGINT | 32 |
| maximum_object_size | JSON 객체의 최대 크기(바이트). | UINTEGER | 16777216 |
format 파라미터는 파일에서 JSON을 어떻게 읽을지 지정합니다. unstructured로 설정하면 최상위 JSON을 읽습니다. 예를 들어 birds.json:
{
"duck": 42
}
{
"goose": [1, 2, 3]
}
FROM read_json_objects('birds.json', format = 'unstructured');
두 개의 객체를 읽는 결과가 됩니다.
┌──────────────────────────────┐
│ json │
│ json │
├──────────────────────────────┤
│ {\n "duck": 42\n} │
│ {\n "goose": [1, 2, 3]\n} │
└──────────────────────────────┘
newline_delimited로 설정하면 NDJSON을 읽습니다. 여기서는 각 JSON이 개행(\n)으로 구분됩니다. 예를 들어 birds-nd.json:
{"duck": 42}
{"goose": [1, 2, 3]}
FROM read_json_objects('birds-nd.json', format = 'newline_delimited');
역시 두 개의 객체를 읽습니다.
┌──────────────────────┐
│ json │
│ json │
├──────────────────────┤
│ {"duck": 42} │
│ {"goose": [1, 2, 3]} │
└──────────────────────┘
array로 설정하면 배열의 각 요소를 읽습니다. 예를 들어 birds-array.json:
[
{
"duck": 42
},
{
"goose": [1, 2, 3]
}
]
FROM read_json_objects('birds-array.json', format = 'array');
역시 두 개의 객체를 읽습니다.
┌──────────────────────────────────────┐
│ json │
│ json │
├──────────────────────────────────────┤
│ {\n "duck": 42\n } │
│ {\n "goose": [1, 2, 3]\n } │
└──────────────────────────────────────┘
JSON을 테이블로 읽는 함수 (Functions for Reading JSON as a Table)
DuckDB는 다음 함수들을 사용해 JSON을 테이블로 읽는 것도 지원합니다.
| Function | Description |
|---|---|
| read_json(filename) | filename에서 JSON을 읽습니다. filename은 파일 목록이나 glob 패턴일 수도 있습니다. |
| read_json_auto(filename) | read_json의 별칭. |
| read_ndjson(filename) | format 파라미터를 newline_delimited로 설정한 read_json의 별칭. |
| read_ndjson_auto(filename) | format 파라미터를 newline_delimited로 설정한 read_json의 별칭. |
파라미터 (Parameters)
위 함수들은 maximum_object_size, format, ignore_errors, compression 외에 다음 파라미터를 추가로 가집니다.
| Name | Description | Type | Default |
|---|---|---|---|
| auto_detect | 키 이름과 값의 데이터 타입을 자동으로 감지할지 여부 | BOOL | true |
| columns | JSON 파일 안에 포함된 키 이름과 값 타입을 지정하는 struct(예: {key1: 'INTEGER', key2: 'VARCHAR'}). auto_detect가 켜져 있으면 추론됨 |
STRUCT | (empty) |
| dateformat | 날짜 파싱에 사용할 날짜 형식 | VARCHAR | iso |
| maximum_depth | 자동 스키마 감지가 타입을 감지하는 최대 중첩 깊이. -1로 설정하면 중첩 JSON 타입을 완전히 감지 | BIGINT | -1 |
| records | auto, true, false 중 하나 | VARCHAR | auto |
| sample_size | 자동 JSON 타입 감지를 위한 샘플 객체 수. 전체 입력 파일을 스캔하려면 -1 | UBIGINT | 20480 |
| timestampformat | 타임스탬프 파싱에 사용할 날짜 형식. iso(기본값)로 설정하면 시간대 오프셋이 있는 ISO 8601 타임스탬프(예: 2024-01-01T12:00:00+05:00)와 분수 초(예: 2024-01-01T12:00:00.123Z)를 자동으로 TIMESTAMP로 추론 |
VARCHAR | iso |
| union_by_name | 여러 JSON 파일의 스키마를 통합할지 여부 | BOOL | false |
| map_inference_threshold | 스키마를 자동 감지할 컬럼 수에 대한 임계값 제어. JSON 스키마 자동 감지가 이 임계값보다 많은 서브필드를 가진 필드에 대해 STRUCT 타입을 추론하면, 대신 MAP 타입을 추론. -1로 설정하면 MAP 추론 비활성화 | BIGINT | 200 |
| field_appearance_threshold | JSON 리더가 각 JSON 필드의 등장 횟수를 자동 감지 샘플 크기로 나눔. 객체의 필드 평균이 이 임계값보다 작으면, 병합된 필드 타입의 값 타입을 가진 MAP 타입을 기본으로 사용 | DOUBLE | 0.1 |
DuckDB는 JSON 배열을 내부 LIST 타입으로 직접 변환하고, 누락된 키는 NULL이 된다는 점을 참고하세요.
SELECT *
FROM read_json(
['birds1.json', 'birds2.json'],
columns = {duck: 'INTEGER', goose: 'INTEGER[]', swan: 'DOUBLE'}
);
| duck | goose | swan |
|---|---|---|
| 42 | [1, 2, 3] | NULL |
| 43 | [4, 5, 6] | 3.3 |
DuckDB는 다음과 같이 타입을 자동으로 감지할 수도 있습니다.
SELECT goose, duck FROM read_json('*.json.gz');
SELECT goose, duck FROM '*.json.gz'; -- 동일한 의미
DuckDB는 format 파라미터로 지정되는 다양한 형식을 읽고 자동 감지할 수 있습니다. 배열을 포함한 JSON 파일을 조회하면, 예를 들어:
[
{
"duck": 42,
"goose": 4.2
},
{
"duck": 43,
"goose": 4.3
}
]
unstructured JSON을 포함한 파일(예: 아래)과 정확히 같은 방식으로 조회할 수 있습니다.
{
"duck": 42,
"goose": 4.2
}
{
"duck": 43,
"goose": 4.3
}
둘 다 같은 테이블로 읽을 수 있습니다.
SELECT
FROM read_json('birds.json');
| duck | goose |
|---|---|
| 42 | 4.2 |
| 43 | 4.3 |
JSON 파일에 "records"가 없는 경우, 즉 객체가 아닌 다른 타입의 JSON이라도 DuckDB는 읽을 수 있습니다. 이때 records 파라미터로 지정합니다. records 파라미터는 JSON 안에 개별 컬럼으로 풀어야 하는 레코드가 들어 있는지 여부를 지정하며, DuckDB는 이를 자동 감지하려고 시도하기도 합니다. 예를 들어 birds-records.json 파일을 보겠습니다.
{"duck": 42, "goose": [1, 2, 3]}
{"duck": 43, "goose": [4, 5, 6]}
SELECT *
FROM read_json('birds-records.json');
이 쿼리는 두 개의 컬럼을 결과로 냅니다.
| duck | goose |
|---|---|
| 42 | [1,2,3] |
| 43 | [4,5,6] |
같은 파일을 records를 false로 설정해서 읽으면, 데이터를 담은 STRUCT 하나(단일 컬럼)로 읽을 수 있습니다.
| json |
|---|
| {'duck': 42, 'goose': [1,2,3]} |
| {'duck': 43, 'goose': [4,5,6]} |
더 복잡한 데이터를 읽는 추가 예제는 "Shredding Deeply Nested JSON, One Vector at a Time" 블로그 포스트를 참고하세요.
FORMAT json과 COPY 문 (Loading with the COPY Statement)
json 확장이 설치되어 있으면 FORMAT json을 COPY FROM, IMPORT DATABASE, COPY TO, EXPORT DATABASE에서 모두 지원합니다. 자세한 내용은 COPY 문과 IMPORT / EXPORT 절을 참고하세요.
기본적으로 COPY는 newline-delimited JSON을 기대합니다. JSON 배열로 데이터를 복사하고 싶다면 ARRAY true를 지정하면 됩니다.
COPY (SELECT * FROM range(5) r(i))
TO 'numbers.json' (ARRAY true);
다음 파일이 생성됩니다.
[
{"i":0},
{"i":1},
{"i":2},
{"i":3},
{"i":4}
]
이것을 다시 DuckDB로 읽으려면 다음과 같이 합니다.
CREATE TABLE numbers (i BIGINT);
COPY numbers FROM 'numbers.json' (ARRAY true);
형식은 다음과 같이 자동 감지할 수도 있습니다.
CREATE TABLE numbers (i BIGINT);
COPY numbers FROM 'numbers.json' (AUTO_DETECT true);
자동 감지된 스키마로 테이블을 만들 수도 있습니다.
CREATE TABLE numbers AS
FROM 'numbers.json';
파라미터 (Parameters)
| Name | Description | Type | Default |
|---|---|---|---|
| auto_detect | 키 이름과 값의 데이터 타입을 자동으로 감지할지 여부 | BOOL | false |
| columns | JSON 파일 안에 포함된 키 이름과 값 타입을 지정하는 struct(예: {key1: 'INTEGER', key2: 'VARCHAR'}). auto_detect가 켜져 있으면 추론됨 |
STRUCT | (empty) |
| compression | 파일의 압축 타입. 기본적으로 파일 확장자에서 자동 감지. 옵션은 uncompressed, gzip, zstd, auto_detect | VARCHAR | auto_detect |
| convert_strings_to_integers | 정수값을 나타내는 문자열을 숫자 타입으로 변환할지 여부 | BOOL | false |
| dateformat | 날짜 파싱에 사용할 날짜 형식 | VARCHAR | iso |
| filename | 결과에 추가 filename 컬럼을 포함할지 여부 | BOOL | false |
| format | auto, unstructured, newline_delimited, array 중 하나 | VARCHAR | array |
| hive_partitioning | 경로를 Hive 파티셔닝으로 해석할지 여부 | BOOL | false |
| ignore_errors | 파싱 오류를 무시할지 여부(format이 newline_delimited일 때만 가능) | BOOL | false |
| maximum_depth | 자동 스키마 감지가 타입을 감지하는 최대 중첩 깊이. -1로 설정하면 중첩 JSON 타입을 완전히 감지 | BIGINT | -1 |
| maximum_object_size | JSON 객체의 최대 크기(바이트) | UINTEGER | 16777216 |
| records | auto, true, false 중 하나 | VARCHAR | records |
| sample_size | 자동 JSON 타입 감지를 위한 샘플 객체 수. 전체 입력 파일을 스캔하려면 -1 | UBIGINT | 20480 |
| timestampformat | 타임스탬프 파싱에 사용할 날짜 형식 | VARCHAR | iso |
| union_by_name | 여러 JSON 파일의 스키마를 통합할지 여부 | BOOL | false |
더 알아보기 (Learn more)
- read_json 관련 함수·파라미터 전체 스펙: JSON 확장 문서
- COPY 문 전체 사용법: COPY
- JSON을 더 파고드는 예제: Shredding Deeply Nested JSON