> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 다른 JSON 포맷 처리

> 다른 JSON 포맷 처리

앞선 JSON 데이터 로드 예시에서는 [`JSONEachRow`](/ko/reference/formats/JSON/JSONEachRow) (`NDJSON`)를 사용한다고 가정합니다. 이 포맷은 각 JSON 줄의 키를 컬럼으로 읽어들입니다. 예시는 다음과 같습니다:

```sql theme={null}
SELECT *
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/pypi/json/*.json.gz', JSONEachRow)
LIMIT 5
```

```response theme={null}
┌───────date─┬─country_code─┬─project────────────┬─type────────┬─installer────┬─python_minor─┬─system─┬─version─┐
│ 2022-11-15 │ CN           │ clickhouse-connect │ bdist_wheel │ bandersnatch │              │        │ 0.2.8   │
│ 2022-11-15 │ CN           │ clickhouse-connect │ bdist_wheel │ bandersnatch │              │        │ 0.2.8   │
│ 2022-11-15 │ CN           │ clickhouse-connect │ bdist_wheel │ bandersnatch │              │        │ 0.2.8   │
│ 2022-11-15 │ CN           │ clickhouse-connect │ bdist_wheel │ bandersnatch │              │        │ 0.2.8   │
│ 2022-11-15 │ CN           │ clickhouse-connect │ bdist_wheel │ bandersnatch │              │        │ 0.2.8   │
└────────────┴──────────────┴────────────────────┴─────────────┴──────────────┴──────────────┴────────┴─────────┘

5 rows in set. Elapsed: 0.449 sec.
```

이는 일반적으로 JSON에서 가장 널리 사용되는 포맷이지만, 다른 포맷을 접하거나 JSON을 단일 객체로 읽어야 하는 경우도 있습니다.

아래에서는 JSON을 다른 일반적인 포맷으로 읽고 로드하는 예시를 제공합니다.

<div id="reading-json-as-an-object">
  ## 객체로 JSON 읽기
</div>

앞선 예시에서는 `JSONEachRow`가 줄바꿈으로 구분된 JSON을 읽는 방식을 보여주었습니다. 각 줄은 별도의 객체로 읽혀 테이블의 한 행에 매핑되고, 각 키는 컬럼에 매핑됩니다. 이 방식은 각 컬럼의 타입이 하나로 고정된, 예측 가능한 JSON에 적합합니다.

반면 `JSONAsObject`는 각 줄을 하나의 `JSON` 객체로 처리해 [`JSON`](/ko/reference/data-types/newjson) 타입의 단일 컬럼에 저장하므로, 중첩된 JSON payload나 키가 동적이고 하나 이상의 타입을 가질 수 있는 경우에 더 적합합니다.

행 단위 삽입에는 `JSONEachRow`를 사용하고, 유연하거나 동적인 JSON 데이터를 저장할 때는 [`JSONAsObject`](/ko/reference/formats/JSON/JSONAsObject)를 사용하십시오.

위 예시와 비교해 보면, 다음 쿼리는 동일한 데이터를 각 줄마다 하나의 JSON 객체로 읽습니다:

```sql theme={null}
SELECT *
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/pypi/json/*.json.gz', JSONAsObject)
LIMIT 5
```

```response theme={null}
┌─json─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ {"country_code":"CN","date":"2022-11-15","installer":"bandersnatch","project":"clickhouse-connect","python_minor":"","system":"","type":"bdist_wheel","version":"0.2.8"} │
│ {"country_code":"CN","date":"2022-11-15","installer":"bandersnatch","project":"clickhouse-connect","python_minor":"","system":"","type":"bdist_wheel","version":"0.2.8"} │
│ {"country_code":"CN","date":"2022-11-15","installer":"bandersnatch","project":"clickhouse-connect","python_minor":"","system":"","type":"bdist_wheel","version":"0.2.8"} │
│ {"country_code":"CN","date":"2022-11-15","installer":"bandersnatch","project":"clickhouse-connect","python_minor":"","system":"","type":"bdist_wheel","version":"0.2.8"} │
│ {"country_code":"CN","date":"2022-11-15","installer":"bandersnatch","project":"clickhouse-connect","python_minor":"","system":"","type":"bdist_wheel","version":"0.2.8"} │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

5 rows in set. Elapsed: 0.338 sec.
```

`JSONAsObject`는 단일 JSON 객체 컬럼을 사용해 테이블에 행을 삽입할 때 유용합니다. 예:

```sql theme={null}
CREATE TABLE pypi
(
    `json` JSON
)
ENGINE = MergeTree
ORDER BY tuple();

INSERT INTO pypi SELECT *
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/pypi/json/*.json.gz', JSONAsObject)
LIMIT 5;

SELECT *
FROM pypi
LIMIT 2;
```

```response theme={null}
┌─json─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ {"country_code":"CN","date":"2022-11-15","installer":"bandersnatch","project":"clickhouse-connect","python_minor":"","system":"","type":"bdist_wheel","version":"0.2.8"} │
│ {"country_code":"CN","date":"2022-11-15","installer":"bandersnatch","project":"clickhouse-connect","python_minor":"","system":"","type":"bdist_wheel","version":"0.2.8"} │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

2 rows in set. Elapsed: 0.003 sec.
```

`JSONAsObject` 포맷은 객체 구조가 일관되지 않은 경우에도 줄바꿈으로 구분된 JSON을 읽는 데 유용할 수 있습니다. 예를 들어, 어떤 키의 타입이 행마다 달라질 수 있습니다(어떤 경우에는 문자열이지만, 다른 경우에는 객체일 수 있음). 이런 경우 ClickHouse는 `JSONEachRow`로 안정적인 스키마를 추론할 수 없으며, `JSONAsObject`를 사용하면 엄격한 타입 검증 없이 데이터를 수집하고 각 JSON 행 전체를 하나의 컬럼에 저장할 수 있습니다. 예를 들어, 다음 예시에서 `JSONEachRow`가 어떻게 실패하는지 확인해 보십시오:

```sql theme={null}
SELECT count()
FROM s3('https://clickhouse-public-datasets.s3.amazonaws.com/bluesky/file_0001.json.gz', 'JSONEachRow')
```

```response theme={null}
Elapsed: 1.198 sec.

Received exception from server (version 24.12.1):
Code: 636. DB::Exception: Received from sql-clickhouse.clickhouse.com:9440. DB::Exception: The table structure cannot be extracted from a JSONEachRow format file. Error:
Code: 117. DB::Exception: JSON objects have ambiguous data: in some objects path 'record.subject' has type 'String' and in some - 'Tuple(`$type` String, cid String, uri String)'. You can enable setting input_format_json_use_string_type_for_ambiguous_paths_in_named_tuples_inference_from_objects to use String type for path 'record.subject'. (INCORRECT_DATA) (version 24.12.1.18239 (official build))
To increase the maximum number of rows/bytes to read for structure determination, use setting input_format_max_rows_to_read_for_schema_inference/input_format_max_bytes_to_read_for_schema_inference.
You can specify the structure manually: (in file/uri bluesky/file_0001.json.gz). (CANNOT_EXTRACT_TABLE_STRUCTURE)
```

반대로, `JSON` 타입은 동일한 서브컬럼에 대해 여러 타입을 지원하므로 이 경우 `JSONAsObject`를 사용할 수 있습니다.

```sql theme={null}
SELECT count()
FROM s3('https://clickhouse-public-datasets.s3.amazonaws.com/bluesky/file_0001.json.gz', 'JSONAsObject')
```

```response theme={null}
┌─count()─┐
│ 1000000 │
└─────────┘

1 row in set. Elapsed: 0.480 sec. Processed 1.00 million rows, 256.00 B (2.08 million rows/s., 533.76 B/s.)
```

<div id="array-of-json-objects">
  ## JSON 객체 배열
</div>

가장 널리 사용되는 JSON 데이터 형식 중 하나는 [이 예시](/ko/assets/list.json)와 같이 JSON 배열에 JSON 객체 목록이 들어 있는 형태입니다:

```bash theme={null}
> cat list.json
[
  {
    "path": "Akiba_Hebrew_Academy",
    "month": "2017-08-01",
    "hits": 241
  },
  {
    "path": "Aegithina_tiphia",
    "month": "2018-02-01",
    "hits": 34
  },
  ...
]
```

이러한 데이터용 테이블을 만들어 보겠습니다:

```sql theme={null}
CREATE TABLE sometable
(
    `path` String,
    `month` Date,
    `hits` UInt32
)
ENGINE = MergeTree
ORDER BY tuple(month, path)
```

JSON 객체 목록을 가져오려면 [`JSONEachRow`](/ko/reference/formats/JSON/JSONEachRow) 포맷을 사용할 수 있습니다([list.json](/ko/assets/list.json) 파일에서 데이터를 삽입):

```sql theme={null}
INSERT INTO sometable
FROM INFILE 'list.json'
FORMAT JSONEachRow
```

로컬 파일의 데이터를 불러오기 위해 [FROM INFILE](/ko/reference/statements/insert-into#inserting-data-from-a-file) 절을 사용했으며, 가져오기가 성공한 것을 확인할 수 있습니다:

```sql theme={null}
SELECT *
FROM sometable
```

```response theme={null}
┌─path──────────────────────┬──────month─┬─hits─┐
│ 1971-72_Utah_Stars_season │ 2016-10-01 │    1 │
│ Akiba_Hebrew_Academy      │ 2017-08-01 │  241 │
│ Aegithina_tiphia          │ 2018-02-01 │   34 │
└───────────────────────────┴────────────┴──────┘
```

<div id="json-object-keys">
  ## JSON 객체의 키
</div>

경우에 따라 JSON 객체 목록은 배열 요소가 아니라 객체 속성으로 인코딩될 수 있습니다([objects.json](/ko/assets/objects.json)을 예시로 참조하십시오):

```bash theme={null}
cat objects.json
```

```response theme={null}
{
  "a": {
    "path":"April_25,_2017",
    "month":"2018-01-01",
    "hits":2
  },
  "b": {
    "path":"Akahori_Station",
    "month":"2016-06-01",
    "hits":11
  },
  ...
}
```

ClickHouse는 [`JSONObjectEachRow`](/ko/reference/formats/JSON/JSONObjectEachRow) 포맷을 사용하여 이러한 종류의 데이터로부터 데이터를 로드할 수 있습니다.

```sql theme={null}
INSERT INTO sometable FROM INFILE 'objects.json' FORMAT JSONObjectEachRow;
SELECT * FROM sometable;
```

```response theme={null}
┌─path────────────┬──────month─┬─hits─┐
│ Abducens_palsy  │ 2016-05-01 │   28 │
│ Akahori_Station │ 2016-06-01 │   11 │
│ April_25,_2017  │ 2018-01-01 │    2 │
└─────────────────┴────────────┴──────┘
```

<div id="specifying-parent-object-key-values">
  ### 상위 객체 키 값 지정
</div>

상위 객체 키의 값도 테이블에 저장하려는 경우를 가정해 보겠습니다. 이 경우, 키 값을 저장할 컬럼 이름을 지정하려면 [다음 옵션](/ko/reference/settings/formats#format_json_object_each_row_column_for_object_name)을 사용할 수 있습니다:

```sql theme={null}
SET format_json_object_each_row_column_for_object_name = 'id'
```

이제 [`file()`](/ko/reference/functions/regular-functions/files#file) 함수를 사용해 원본 JSON 파일에서 어떤 데이터가 로드되는지 확인할 수 있습니다:

```sql theme={null}
SELECT * FROM file('objects.json', JSONObjectEachRow)
```

```response theme={null}
┌─id─┬─path────────────┬──────month─┬─hits─┐
│ a  │ April_25,_2017  │ 2018-01-01 │    2 │
│ b  │ Akahori_Station │ 2016-06-01 │   11 │
│ c  │ Abducens_palsy  │ 2016-05-01 │   28 │
└────┴─────────────────┴────────────┴──────┘
```

`id` 컬럼이 키 값으로 올바르게 채워진 것을 확인하세요.

<div id="json-arrays">
  ## JSON 배열
</div>

공간을 절약하기 위해 JSON 파일을 객체 대신 배열로 인코딩하는 경우가 있습니다. 이 경우 [JSON 배열 목록](/ko/assets/arrays.jsonl)을 사용합니다:

```bash theme={null}
cat arrays.json
```

```response theme={null}
["Akiba_Hebrew_Academy", "2017-08-01", 241],
["Aegithina_tiphia", "2018-02-01", 34],
["1971-72_Utah_Stars_season", "2016-10-01", 1]
```

이 경우 ClickHouse는 이 데이터를 로드한 뒤, 배열의 순서에 따라 각 값을 해당 컬럼에 매핑합니다. 이를 위해 [`JSONCompactEachRow`](/ko/reference/formats/JSON/JSONCompactEachRow) 포맷을 사용합니다:

```sql theme={null}
SELECT * FROM sometable
```

```response theme={null}
┌─c1────────────────────────┬─────────c2─┬──c3─┐
│ Akiba_Hebrew_Academy      │ 2017-08-01 │ 241 │
│ Aegithina_tiphia          │ 2018-02-01 │  34 │
│ 1971-72_Utah_Stars_season │ 2016-10-01 │   1 │
└───────────────────────────┴────────────┴─────┘
```

<div id="importing-individual-columns-from-json-arrays">
  ### JSON 배열에서 개별 컬럼 가져오기
</div>

경우에 따라 데이터는 행 단위가 아니라 컬럼 단위로 인코딩될 수 있습니다. 이 경우 상위 JSON 객체는 값을 담은 컬럼을 포함합니다. [다음 파일](/ko/assets/columns.json)을 확인하십시오:

```bash theme={null}
cat columns.json
```

```response theme={null}
{
  "path": ["2007_Copa_America", "Car_dealerships_in_the_USA", "Dihydromyricetin_reductase"],
  "month": ["2016-07-01", "2015-07-01", "2015-07-01"],
  "hits": [178, 11, 1]
}
```

ClickHouse는 다음과 같은 형식의 데이터를 파싱하기 위해 [`JSONColumns`](/ko/reference/formats/JSON/JSONColumns) 포맷을 사용합니다:

```sql theme={null}
SELECT * FROM file('columns.json', JSONColumns)
```

```response theme={null}
┌─path───────────────────────┬──────month─┬─hits─┐
│ 2007_Copa_America          │ 2016-07-01 │  178 │
│ Car_dealerships_in_the_USA │ 2015-07-01 │   11 │
│ Dihydromyricetin_reductase │ 2015-07-01 │    1 │
└────────────────────────────┴────────────┴──────┘
```

객체 대신 [컬럼 배열](/ko/assets/columns-array.json)을 다룰 때 사용할 수 있는 더 간결한 [`JSONCompactColumns`](/ko/reference/formats/JSON/JSONCompactColumns) 포맷도 지원됩니다:

```sql theme={null}
SELECT * FROM file('columns-array.json', JSONCompactColumns)
```

```response theme={null}
┌─c1──────────────┬─────────c2─┬─c3─┐
│ Heidenrod       │ 2017-01-01 │ 10 │
│ Arthur_Henrique │ 2016-11-01 │ 12 │
│ Alan_Ebnother   │ 2015-11-01 │ 66 │
└─────────────────┴────────────┴────┘
```

<div id="saving-json-objects-instead-of-parsing">
  ## 파싱하지 않고 JSON 객체 저장하기
</div>

JSON 객체를 파싱하지 않고 하나의 `String`(또는 `JSON`) 컬럼에 저장하는 편이 나은 경우도 있습니다. 이는 구조가 서로 다른 JSON 객체 목록을 다룰 때 유용합니다. 예를 들어 [이 파일](/ko/assets/custom.json)에는 상위 목록 안에 서로 다른 JSON 객체가 여러 개 들어 있습니다:

```bash theme={null}
cat custom.json
```

```response theme={null}
[
  {"name": "Joe", "age": 99, "type": "person"},
  {"url": "/my.post.MD", "hits": 1263, "type": "post"},
  {"message": "Warning on disk usage", "type": "log"}
]
```

원본 JSON 객체를 다음 테이블(table)에 저장합니다:

```sql theme={null}
CREATE TABLE events
(
    `data` String
)
ENGINE = MergeTree
ORDER BY ()
```

이제 JSON 객체를 파싱하지 않고 그대로 유지하려면 [`JSONAsString`](/ko/reference/formats/JSON/JSONAsString) 포맷을 사용해 파일의 데이터를 이 테이블로 로드할 수 있습니다:

```sql theme={null}
INSERT INTO events (data)
FROM INFILE 'custom.json'
FORMAT JSONAsString
```

또한 저장된 객체를 쿼리하는 데 [JSON functions](/ko/reference/functions/regular-functions/json-functions)을 사용할 수 있습니다:

```sql theme={null}
SELECT
    JSONExtractString(data, 'type') AS type,
    data
FROM events
```

```response theme={null}
┌─type───┬─data─────────────────────────────────────────────────┐
│ person │ {"name": "Joe", "age": 99, "type": "person"}         │
│ post   │ {"url": "/my.post.MD", "hits": 1263, "type": "post"} │
│ log    │ {"message": "Warning on disk usage", "type": "log"}  │
└────────┴──────────────────────────────────────────────────────┘
```

`JSONAsString`은 JSON 객체가 줄마다 하나씩 있는 형식의 파일(일반적으로 `JSONEachRow` 포맷과 함께 사용됨)에서 문제없이 작동합니다.

<div id="schema-for-nested-objects">
  ## 중첩된 객체용 스키마
</div>

[중첩된 JSON 객체](/ko/assets/list-nested.json)를 다룰 때는 명시적인 스키마를 추가로 정의하고, 복합 타입([`Array`](/ko/reference/data-types/array), [`JSON`](/ko/guides/clickhouse/data-formats/json/intro) 또는 [`Tuple`](/ko/reference/data-types/tuple))을 사용해 데이터를 로드할 수 있습니다:

```sql theme={null}
SELECT *
FROM file('list-nested.json', JSONEachRow, 'page Tuple(path String, title String, owner_id UInt16), month Date, hits UInt32')
LIMIT 1
```

```response theme={null}
┌─page───────────────────────────────────────────────┬──────month─┬─hits─┐
│ ('Akiba_Hebrew_Academy','Akiba Hebrew Academy',12) │ 2017-08-01 │  241 │
└────────────────────────────────────────────────────┴────────────┴──────┘
```

<div id="accessing-nested-json-objects">
  ## 중첩된 JSON 객체에 접근하기
</div>

[다음 설정 옵션](/ko/reference/settings/formats#input_format_import_nested_json)을 활성화하면 [중첩된 JSON 키](/ko/assets/list-nested.json)를 참조할 수 있습니다:

```sql theme={null}
SET input_format_import_nested_json = 1
```

이를 통해 점 표기법을 사용해 중첩된 JSON 객체 키를 참조할 수 있습니다(작동하려면 해당 키를 백틱(\`)으로 감싸야 한다는 점을 기억하십시오):

```sql theme={null}
SELECT *
FROM file('list-nested.json', JSONEachRow, '`page.owner_id` UInt32, `page.title` String, month Date, hits UInt32')
LIMIT 1
```

```results theme={null}
┌─page.owner_id─┬─page.title───────────┬──────month─┬─hits─┐
│            12 │ Akiba Hebrew Academy │ 2017-08-01 │  241 │
└───────────────┴──────────────────────┴────────────┴──────┘
```

이렇게 하면 중첩된 JSON 객체를 펼치거나, 일부 중첩 값을 별도의 컬럼으로 저장할 수 있습니다.

<div id="skipping-unknown-columns">
  ## 알 수 없는 컬럼 건너뛰기
</div>

기본적으로 ClickHouse는 JSON 데이터를 가져올 때 알 수 없는 컬럼을 무시합니다. 이제 `month` 컬럼이 없는 테이블로 원본 파일을 가져와 보겠습니다:

```sql theme={null}
CREATE TABLE shorttable
(
    `path` String,
    `hits` UInt32
)
ENGINE = MergeTree
ORDER BY path
```

3개의 컬럼으로 이루어진 [원본 JSON 데이터](/ko/assets/list.json)를 이 테이블에 계속 삽입할 수 있습니다:

```sql theme={null}
INSERT INTO shorttable FROM INFILE 'list.json' FORMAT JSONEachRow;
SELECT * FROM shorttable
```

```response theme={null}
┌─path──────────────────────┬─hits─┐
│ 1971-72_Utah_Stars_season │    1 │
│ Aegithina_tiphia          │   34 │
│ Akiba_Hebrew_Academy      │  241 │
└───────────────────────────┴──────┘
```

ClickHouse는 가져오는 과정에서 알 수 없는 컬럼을 무시합니다. 이 동작은 [input\_format\_skip\_unknown\_fields](/ko/reference/settings/formats#input_format_skip_unknown_fields) 설정 옵션을 사용하여 비활성화할 수 있습니다:

```sql theme={null}
SET input_format_skip_unknown_fields = 0;
INSERT INTO shorttable FROM INFILE 'list.json' FORMAT JSONEachRow;
```

```response theme={null}
Ok.
Exception on client:
Code: 117. DB::Exception: Unknown field found while parsing JSONEachRow format: month: (in file/uri /data/clickhouse/user_files/list.json): (at row 1)
```

ClickHouse는 JSON과 테이블의 컬럼 구조가 일치하지 않는 경우 예외를 발생시킵니다.

<div id="bson">
  ## BSON
</div>

ClickHouse는 [BSON](https://bsonspec.org/)으로 인코딩된 파일로 데이터를 내보내고, 이러한 파일에서 데이터를 가져올 수 있습니다. 이 포맷은 일부 DBMS에서 사용되며, 예를 들어 [MongoDB](https://github.com/mongodb/mongo) 데이터베이스에서 사용됩니다.

BSON 데이터를 가져오려면 [BSONEachRow](/ko/reference/formats/BSONEachRow) 포맷을 사용합니다. [이 BSON 파일](/ko/assets/data.bson)에서 데이터를 가져와 보겠습니다:

```sql theme={null}
SELECT * FROM file('data.bson', BSONEachRow)
```

```response theme={null}
┌─path──────────────────────┬─month─┬─hits─┐
│ Bob_Dolman                │ 17106 │  245 │
│ 1-krona                   │ 17167 │    4 │
│ Ahmadabad-e_Kalij-e_Sofla │ 17167 │    3 │
└───────────────────────────┴───────┴──────┘
```

같은 포맷으로 BSON 파일로도 내보낼 수 있습니다:

```sql theme={null}
SELECT *
FROM sometable
INTO OUTFILE 'out.bson'
FORMAT BSONEachRow
```

이후 데이터가 `out.bson` 파일로 내보내집니다.
