:meta-keywords: cubrid json, json functions, database json, JSON_TABLE :meta-description: CUBRID functions that create, query and modify JSON data. :tocdepth: 3 .. _json-fn: ********* JSON 함수 ********* .. _fn-json-intro: JSON 함수 소개 =================================== ì´ ì„¹ì…˜ì—서는 JSON ë°ì´í„° ê´€ë ¨ ë™ìž‘ì— ëŒ€í•´ ê¸°ìˆ í•œë‹¤. ì§€ì›í•˜ëŠ” JSON í•¨ìˆ˜ë“¤ì€ ë‹¤ìŒ í‘œì™€ 같다: +------------------+------------------+------------------+------------------+ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | | \arrow` | \contains-path` | \merge-patch` | \replace` | +------------------+------------------+------------------+------------------+ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | | \double-arrow` | \depth` | \merge-preserve` | \search` | +------------------+------------------+------------------+------------------+ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | | \array` | \extract` | \object` | \set` | +------------------+------------------+------------------+------------------+ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | | \arrayagg` | \insert` | \objectagg` | \table` | +------------------+------------------+------------------+------------------+ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | | \array-append` | \keys` | \pretty` | \type` | +------------------+------------------+------------------+------------------+ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | | \array-insert` | \length` | \quote` | \unquote` | +------------------+------------------+------------------+------------------+ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | :ref:`fn-json-\ | | \contains` | \merge` | \remove` | \valid` | +------------------+------------------+------------------+------------------+ í•¨ìˆ˜ì˜ ìž…ë ¥ ì¸ìžëŠ” 아래와 ê°™ì€ ëª‡ê°€ì§€ ìœ í˜•ì„ ê°€ì§„ë‹¤. - *json_doc*: JSONì´ë‚˜ JSON으로 파싱ë˜ëŠ” 문ìžì—´ - *val*: JSONì´ë‚˜ JSON ì§€ì› ìŠ¤ì¹¼ë¼ íƒ€ìž… 중 하나로 í•´ì„ë 수 있는 ê°’ - *json key*: 키 ì´ë¦„ìœ¼ë¡œì„œì˜ ë¬¸ìžì—´ - *json path/pointer*: :ref:`json-path` 와 :ref:`json-pointer` ì— ì„¤ëª…ëœ ê·œì¹™ì„ ë”°ë¥´ëŠ” 문ìžì—´ .. note:: JSON 함수 문ìžì—´ ì¸ìžì˜ ì½”ë“œì…‹ì€ UTF8ì„ ê¸°ì¤€ìœ¼ë¡œ 한다. 다른 ì½”ë“œì…‹ì˜ ìž…ë ¥ 문ìžì—´ì€ UTF8로 변환ëœë‹¤. UTF8ì´ ì•„ë‹Œ 코드셋 문ìžì—´ì— 대한 ëŒ€ì†Œë¬¸ìž êµ¬ë³„ 없는 ê²€ìƒ‰ì€ ê¸°ëŒ€ì™€ 다른 결과가 나올 수 있다. 다ìŒì˜ 표는 ìž…ë ¥ ì¸ìžë¥¼ í•´ì„í•˜ëŠ”ë° ìžˆì–´ì„œ *json_doc* 와 *val* ì˜ ì°¨ì´ë¥¼ ë³´ì—¬ì£¼ê³ ìžˆë‹¤: +-------------------+-----------------------------+----------------------------------+ | ìž…ë ¥ 타입 | *json_doc* | *val* | +===================+=============================+==================================+ | JSON | ìž…ë ¥ ê°’ì´ ë³€í•˜ì§€ ì•ŠìŒ | ìž…ë ¥ ê°’ì´ ë³€í•˜ì§€ ì•ŠìŒ | +-------------------+-----------------------------+----------------------------------+ | String | JSON ìž…ë ¥ ê°’ì´ íŒŒì‹±ë¨ | ìž…ë ¥ ê°’ì´ JSON STRING으로 ë³€í™˜ë¨ | +-------------------+-----------------------------+----------------------------------+ | Short, Integer | 변환 오류 | ìž…ë ¥ ê°’ì´ JSON INTEGER로 ë³€í™˜ë¨ | +-------------------+-----------------------------+----------------------------------+ | Bigint | 변환 오류 | ìž…ë ¥ ê°’ì´ JSON BIGINT로 ë³€í™˜ë¨ | +-------------------+-----------------------------+----------------------------------+ | Float, Double, | 변환 오류 | ìž…ë ¥ ê°’ì´ JSON DOUBLE로 ë³€í™˜ë¨ | +-------------------+-----------------------------+----------------------------------+ | NULL | NULL | ìž…ë ¥ ê°’ì´ JSON_NULL로 ë³€í™˜ë¨ | +-------------------+-----------------------------+----------------------------------+ | Other | 변환 오류 | 변환 오류 | +-------------------+-----------------------------+----------------------------------+ .. _fn-json-array: JSON_ARRAY =================================== .. function:: JSON_ARRAY ([val1 [ , val2] ...]) **JSON_ARRAY** 함수는 해당 값들(val, val2, ..)ì„ ê°€ì§„ 리스트(텅빈 ë¦¬ìŠ¤íŠ¸ë„ ê°€ëŠ¥)ê°€ í¬í•¨ëœ json ë°°ì—´ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_ARRAY(); :: json_array() ====================== [] .. code-block:: sql SELECT JSON_ARRAY(1, '1', json '{"a":4}', json '[1,2,3]'); :: json_array(1, '1', json '{"a":4}', json '[1,2,3]') ====================== [1,"1",{"a":4},[1,2,3]] .. _fn-json-object: JSON_OBJECT =================================== .. function:: JSON_OBJECT ([key1, val1 [ , key2, val2] ...]) **JSON_OBJECT** 함수는 해당 키/ê°’(key, val1, key, val2,...)ìŒì„ 가진 리스트(텅빈 ë¦¬ìŠ¤íŠ¸ë„ ê°€ëŠ¥)ê°€ í¬í•¨ëœ json ê°ì²´ë¥¼ 반환한다. .. code-block:: sql SELECT JSON_OBJECT(); :: json_object() ====================== {} .. code-block:: sql SELECT JSON_OBJECT('a', 1, 'b', '1', 'c', json '{"a":4}', 'd', json '[1,2,3]'); :: json_object('a', 1, 'b', '1', 'c', json '{"a":4}', 'd', json '[1,2,3]') ====================== {"a":1,"b":"1","c":{"a":4},"d":[1,2,3]} .. _fn-json-keys: JSON_KEYS =================================== .. function:: JSON_KEYS (json_doc [ , json path]) **JSON_KEYS** 함수는 해당 패스로 주어진 json ê°ì²´ì˜ ëª¨ë“ í‚¤ê°’ì„ ê°€ì§„ json ë°°ì—´ì„ ë°˜í™˜í•œë‹¤. 해당 경로가 json ê°ì²´ê°€ 아닌 json 요소를 ì§€ì •í•˜ë©´ json nullì´ ë°˜í™˜ëœë‹¤. json 경로 ì¸ìžê°€ 누ë½ë˜ë©´ 키(key)는 json 루트 요소로부터 ê°€ì ¸ì˜¨ë‹¤. *json 경로* ê°€ 존재하지 않으면 오류가 ë°œìƒí•˜ê³ *json_doc* ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_KEYS('{}'); :: json_keys('{}') ====================== [] .. code-block:: sql SELECT JSON_KEYS('"non-object"'); :: json_keys('"non-object"') ====================== null .. code-block:: sql SELECT JSON_KEYS('{"a":1, "b":2, "c":{"d":1}}'); :: json_keys('{"a":1, "b":2, "c":{"d":1}}') ====================== ["a","b","c"] .. _fn-json-depth: JSON_DEPTH =================================== .. function:: JSON_DEPTH (json_doc) **JSON_DEPTH** 함수는 jsonì˜ ìµœëŒ€ 깊ì´ë¥¼ 반환한다. 깊ì´ëŠ” 1부터 시작하며 ê¹Šì´ ë ˆë²¨ì€ ë¹„ì–´ìžˆì§€ ì•Šì€ json ë°°ì—´ì´ë‚˜ 비어있지 ì•Šì€ json ê°ì²´ì—서 1씩 ì¦ê°€í•œë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_DEPTH('"scalar"'); :: json_depth('"scalar"') ====================== 1 .. code-block:: sql SELECT JSON_DEPTH('[{"a":4}, 2]'); :: json_depth('[{"a":4}, 2]') ====================== 3 [ì˜ˆì œ] deeper json: .. code-block:: sql SELECT JSON_DEPTH('[{"a":[1,2,3,{"k":[4,5]}]},2,3,4,5,6,7]'); :: json_depth('[{"a":[1,2,3,{"k":[4,5]}]},2,3,4,5,6,7]') ====================== 6 .. _fn-json-length: JSON_LENGTH =================================== .. function:: JSON_LENGTH (json_doc [ , json path]) **JSON_LENGTH** 함수는 주어진 ê²½ë¡œì— ìžˆëŠ” json ìš”ì†Œì˜ ê¸¸ì´ë¥¼ 반환한다. 경로 ì¸ìžê°€ 주어지지 않으면 josn 루트 ìš”ì†Œì˜ ê¸¸ì´ê°€ 반환ëœë‹¤. ì¸ìžê°€ **NULL** ì´ê±°ë‚˜ 해당 ê²½ë¡œì— ì–´ë–¤ ìš”ì†Œë„ ì¡´ìž¬í•˜ì§€ 않으면 **NULL** ì´ ë°˜í™˜ëœë‹¤. .. code-block:: sql SELECT JSON_LENGTH('"scalar"'); :: json_length('"scalar"') ====================== 1 .. code-block:: sql SELECT JSON_LENGTH('[{"a":4}, 2]', '$.a'); :: json_length('[{"a":4}, 2]', '$.a') ====================== NULL .. code-block:: sql SELECT JSON_LENGTH('[2, {"a":4, "b":4, "c":4}]', '$[1]'); :: json_length('[2, {"a":4, "b":4, "c":4}]', '$[1]') ====================== 3 .. code-block:: sql SELECT JSON_LENGTH('[{"a":[1,2,3,{"k":[4,5,6,7,8]}]},2]'); :: json_length('[{"a":[1,2,3,{"k":[4,5,6,7,8]}]},2]') ====================== 2 .. _fn-json-valid: JSON_VALID =================================== .. function:: JSON_VALID (val) **JSON_VALID** 함수는 해당 *val* ì¸ìžê°€ ìœ íš¨í•œ json_docì¼ ê²½ìš°ì— 1ì„ ê·¸ë ‡ì§€ ì•Šì€ ê²½ìš°ì— 0ì„ ë°˜í™˜í•œë‹¤. 해당 ì¸ìžê°€ **NULL** ì¸ ê²½ìš° **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_VALID('[{"a":4}, 2]'); 1 SELECT JSON_VALID('{"wrong json object":'); 0 .. _fn-json-type: JSON_TYPE =================================== .. function:: JSON_TYPE (json_doc) **JSON_TYPE** 함수는 문ìžì—´ ì¸ìžì¸ *json_doc* ì˜ íƒ€ìž…ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_TYPE ('[{"a":4}, 2]'); 'JSON_ARRAY' SELECT JSON_TYPE ('{"a":4}'); 'JSON_OBJECT' SELECT JSON_TYPE ('"aaa"'); 'STRING' .. _fn-json-quote: JSON_QUOTE =================================== .. function:: JSON_QUOTE (str) **JSON_QUOTE** 함수는 문ìžì—´ê³¼ ì´ìŠ¤ì¼€ì´í”„ëœ íŠ¹ìˆ˜ 문ìžë“¤ì„ í°ë”°ì˜´í‘œë¡œ ë¬¶ì€ json_stringì„ ê²°ê³¼ë¡œ 반환한다. *str* ì¸ìžê°€ **NULL** ì¸ ê²½ìš° **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_QUOTE ('simple'); :: json_unquote('simple') ====================== '"simple"' .. code-block:: sql SELECT JSON_QUOTE ('"'); :: json_unquote('"') ====================== '"\""' .. _fn-json-unquote: JSON_UNQUOTE =================================== .. function:: JSON_UNQUOTE (json_doc) **JSON_UNQUOTE** 함수는 따옴표로 묶ì´ì§€ ì•Šì€ json_value 문ìžì—´ì„ 반환한다. *json_doc* ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_UNQUOTE ('"\\u0032"'); :: json_unquote('"\u0032"') ====================== '2' .. code-block:: sql SELECT JSON_UNQUOTE ('"\\""'); :: json_unquote('"\""') ====================== '"' .. _fn-json-pretty: JSON_PRETTY =================================== .. function:: JSON_PRETTY (json_doc) **JSON_PRETTY** 는 *json_doc* 보기좋게 ì¶œë ¥ëœ ë¬¸ìžì—´ì„ 반환한다. *json_doc* ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_PRETTY('[{"a":"val1", "b":"val2", "c": [1, "elem2", 3, 4, {"key":"val"}]}]'); :: json_pretty('[{"a":"val1", "b":"val2", "c": [1, "elem2", 3, 4, {"key":"val"}]}]') ====================== '[ { "a": "val1", "b": "val2", "c": [ 1, "elem2", 3, 4, { "key": "val" } ] } ]' .. _fn-json-search: JSON_SEARCH =================================== .. function:: JSON_SEARCH (json_doc, one/all, search_str [, escape_char [, json path] ...]) **JSON_SEARCH** 함수는 해당 *search_str* ê³¼ ì¼ì¹˜í•˜ëŠ” json 문ìžì—´ì„ í¬í•¨í•œ í•˜ë‚˜ì˜ json 경로 í˜¹ì€ ë³µìˆ˜ì˜ json 경로를 반환한다. ì¼ì¹˜ 여부 검사는 ë‚´ë¶€ì˜ json 문ìžì—´ê³¼ *search_str* ì— **LIKE** ì—°ì‚°ìžë¥¼ ì 용하여 수행ëœë‹¤. **JSON_SEARCH** ì˜ *escape_char* ë° *search_str* ì— ëŒ€í•´ **LIKE** ì—°ì‚°ìžì˜ ëŒ€ì‘ ë¶€ë¶„ê³¼ ë™ì¼í•œ ê·œì¹™ì´ ì ìš©ëœë‹¤. **LIKE** ê´€ë ¨ ê·œì¹™ì— ëŒ€í•œ 추가 ì„¤ëª…ì€ :ref:`like-expr` ì„ ì°¸ê³ í•œë‹¤. one/allì—서 'one'ì„ ì‚¬ìš©í•˜ë©´ **JSON_SEARCH** 첫번째 ì¼ì¹˜ê°€ ë‚˜íƒ€ë‚¬ì„ ë•Œ íƒìƒ‰ì´ 멈추게 ëœë‹¤. ë°˜ë©´ì— 'all'ì„ ì‚¬ìš©í•˜ë©´ *search_str* ê³¼ ì¼ì¹˜í•˜ëŠ” ëª¨ë“ ê²½ë¡œë¥¼ íƒìƒ‰í•˜ê²Œ ëœë‹¤. 주어진 json 경로는 반환 ëœ ê²½ë¡œì˜ í•„í„°ë¥¼ ê²°ì •í•˜ë¯€ë¡œ 결과로 나온 json ê²½ë¡œì˜ ì ‘ë‘사(prefix)는 ì ì–´ë„ í•˜ë‚˜ì˜ ì£¼ì–´ì§„ json 경로 ì¸ìžì™€ ì¼ì¹˜í•´ì•¼ 한다. json 경로 ì¸ìžê°€ 누ë½ëœ 경우, **JSON_SEARCH** 는 루트 요소로 부터 íƒìƒ‰ì„ 시작한다. .. code-block:: sql SELECT JSON_SEARCH('{"a":["a","b"],"b":"a","c":"a"}', 'one', 'a'); :: json_search('{"a":["a","b"],"b":"a","c":"a"}', 'one', 'a') ====================== "$.a[0]" .. code-block:: sql SELECT JSON_SEARCH('{"a":["a","b"],"b":"a","c":"a"}', 'all', 'a'); :: json_search('{"a":["a","b"],"b":"a","c":"a"}', 'all', 'a') ====================== "["$.a[0]","$.b","$.c"]" .. code-block:: sql SELECT JSON_SEARCH('{"a":["a","b"],"b":"a","c":"a"}', 'all', 'a', NULL, '$.a', '$.b'); :: json_search('{"a":["a","b"],"b":"a","c":"a"}', 'all', 'a', null, '$.a', '$.b') ====================== "["$.a[0]","$.b"]" 와ì¼ë“œì¹´ë“œëŠ” ì¢€ë” ì¼ë°˜ì ì¸ í˜•ì‹ì˜ 경로 필터로 사용ë 수 있다. json 경로는 ê°ì²´ 키 ì‹ë³„ìžë¡œ 시작하는 것만 허용ëœë‹¤. .. code-block:: sql SELECT JSON_SEARCH('{"a":["a","b"],"b":"a","c":"a"}', 'all', 'a', NULL, '$.*'); :: json_search('{"a":["a","b"],"b":"a","c":"a"}', 'all', 'a', null, '$.*') ====================== "["$.a[0]","$.b","$.c"]" ê°ì²´ 키(key) ì‹ë³„ìžë¡œ ì‹œìž‘í•˜ê³ json ë°°ì—´ ì¸ë±ìŠ¤ë¥¼ 따르는 json 경로만 í—ˆìš©í•¨ìœ¼ë¡œì¨ '$.b', '$.d.e[0]' ì¼ì¹˜ í•ëª©ì´ í•„í„°ë§ ëœë‹¤: .. code-block:: sql SELECT JSON_SEARCH('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', 'all', 'a', NULL, '$.*[*]'); :: json_search('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', 'all', 'a', null, '$.*[*]') ====================== "["$.a[0]","$.c[0]"]" json ë°°ì—´ ì¸ë±ìŠ¤ë¥¼ í¬í•¨í•˜ëŠ” json 경로만 í—ˆìš©í•¨ìœ¼ë¡œì¨ '$.b'ê°€ í•„í„°ë§ ëœë‹¤. .. code-block:: sql SELECT JSON_SEARCH('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', 'all', 'a', NULL, '$**[*]'); :: json_search('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', 'all', 'a', null, '$**[*]') ====================== "["$.a[0]","$.c[0]","$.d.e[0]"]" .. _fn-json-extract: JSON_EXTRACT =================================== .. function:: JSON_EXTRACT (json_doc, json path [, json path] ...) 해당 경로로 ì§€ì •ëœ *json_doc* 로부터 json 요소를 반환한다. json 경로 ì¸ìžê°€ 와ì¼ë“œì¹´ë“œë¥¼ í¬í•¨í•˜ëŠ” 경우 와ì¼ë“œì¹´ë“œì— ì˜í•´ í¬í•¨ë 수 있는 ëª¨ë“ ê²½ë¡œì˜ ì§€ì •ëœ json 요소가 json ë°°ì—´ 결과로 반환ëœë‹¤. 와ì¼ë“œì¹´ë“œë¥¼ 사용하지 ì•Šê³ json 경로ì—서 í•˜ë‚˜ì˜ ìš”ì†Œë§Œ ë°œê²¬ëœ ê²½ìš° í•˜ë‚˜ì˜ json 요소만 반환ë˜ë©°, ê·¸ë ‡ì§€ ì•Šì€ ê²½ìš° ë°œê²¬ëœ json 요소는 json 배열로 구성하여 반환ëœë‹¤. json 경로가 **NULL** ì´ê±°ë‚˜ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° í˜¹ì€ *json_doc* ì¸ìžê°€ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° ì—러가 반환ëœë‹¤. json 요소가 발견ë˜ì§€ 않거나 json_docì´ **NULL** ì¸ ê²½ìš° **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT JSON_EXTRACT('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$.a'); :: json_extract('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$.a') ====================== "["a","b"]" -- at '$.a' we have the json array ["a","b"] .. code-block:: sql SELECT JSON_EXTRACT('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$.a[*]'); :: json_extract('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$.a[*]') ====================== "["a","b"]" -- '$.a[0]'와 '$.a[1]'는 json 배열로 구성하여, ["a","b"]를 형성한다. 와ì¼ë“œ 카드'.*'를 í¬í•¨í•œ ì´ì „ì˜ ì¿¼ë¦¬ë¥¼ '.a'로 바꾸면 '$.c[0]'ê°€ ì¼ì¹˜í• 것ì¸ë°, ì´ê²ƒì€ ì •í™•ížˆ ê°ì²´ 키(key) ì‹ë³„ìžì™€ ë°°ì—´ ì¸ë±ìŠ¤ê°€ 있는 ëª¨ë“ json 경로와 ì¼ì¹˜í• 것ì´ë‹¤. .. code-block:: sql SELECT JSON_EXTRACT('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$.*[*]'); :: json_extract('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$.*[*]') ====================== "["a","b","a"]" ë‹¤ìŒ json 경로는 json ë°°ì—´ ì¸ë±ìŠ¤ë¡œ ë나는 ëª¨ë“ json 경로와 ì¼ì¹˜í• 것ì´ë‹¤ (ì´ì „ì˜ ì¼ì¹˜í•˜ëŠ” ëª¨ë“ ê²½ë¡œ ë° '$ .d.e [0]'ê³¼ ì¼ì¹˜): .. code-block:: sql SELECT JSON_EXTRACT('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$**[*]'); :: json_extract('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$**[*]') ====================== "["a","b","a","a"]" .. code-block:: sql SELECT JSON_EXTRACT('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$.d**[*]'); :: json_extract('{"a":["a","b"],"b":"a","c":["a"], "d":{"e":["a"]}}', '$d**[*]') ====================== "["a"]" -- '$.d.e[0]'ì€ í•´ë‹¹ ì¸ìžì˜ 경로 패밀리와 ì¼ì¹˜í•˜ëŠ” ìœ ì¼í•œ 경로ì´ë©°, .d'로 ì‹œìž‘í•˜ê³ ë°°ì—´ ì¸ë±ìŠ¤ë¡œ ë나는 경로ì´ë‹¤. .. _fn-json-arrow: -> =================================== .. function:: json_doc -> json path *json_doc* ì¸ìžê°€ í•˜ë‚˜ì˜ ì»¬ëŸ¼ìœ¼ë¡œ ì œí•œëœ ë‘ ê°œì˜ ì¸ìžë¥¼ 가지는 **JSON_EXTRACT** ì˜ ë³„ì¹ ì—°ì‚°ìž. json 경로가 **NULL** ì´ê±°ë‚˜ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류를 반환한다. **NULL** *josn_doc* ì¸ìžê°€ ì ìš©ëœ ê²½ìš°ì—는 **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql CREATE TABLE tj (a json); INSERT INTO tj values ('{"a":1}'), ('{"a":2}'), ('{"a":3}'), (NULL); SELECT a->'$.a' from tj; :: json_extract(a, '$.a') ====================== 1 2 3 NULL .. _fn-json-double-arrow: ->> =================================== .. function:: json_doc ->> json path **JSON_UNQUOTE** ì˜ ë³„ì¹ (json_doc->json 경로). 본 ì—°ì‚°ìžëŠ” ì»¬ëŸ¼ì¸ *json_doc* ì¸ìžì—ë§Œ ì ìš© í• ìˆ˜ 있다. json 경로가 **NULL** ì´ê±°ë‚˜ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류가 ë°œìƒí•œë‹¤. **NULL** *json_doc* ì¸ìžì— ì ìš©ëœ ê²½ìš° **NULL** ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql CREATE TABLE tj (a json); INSERT INTO tj values ('{"a":1}'), ('{"a":2}'), ('{"a":3}'), (NULL); SELECT a->>'$.a' from tj; :: json_unquote(json_extract(a, '$.a')) ====================== '1' '2' '3' NULL .. _fn-json-contains-path: JSON_CONTAINS_PATH =================================== .. function:: JSON_CONTAINS_PATH (json_doc, one/all, json path [, json path] ...) **JSON_CONTAINS_PATH** 함수는 해당 경로가 *json_doc* ë‚´ì— ì¡´ìž¬í•˜ëŠ”ì§€ë¥¼ 검사한다. one/all ì¸ìž 중 'all'ì´ ì ìš©ëœ ê²½ìš° ëª¨ë“ ê²½ë¡œê°€ 존재하면 1ì„ ë°˜í™˜í•˜ê³ ê·¸ë ‡ì§€ 않으면 0ì„ ë°˜í™˜í•œë‹¤. one/all ì¸ìž 중 'one'ì´ ì ìš©ëœ ê²½ìš° í•˜ë‚˜ì˜ ê²½ë¡œë¼ë„ 존재하면 1ì„ ë°˜í™˜í•˜ê³ ê·¸ë ‡ì§€ 않으면 0ì„ ë°˜í™˜í•œë‹¤. 해당 ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. 해당 ì¸ìžê°€ ìœ íš¨í•˜ì§€ 않으면 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_CONTAINS_PATH ('[{"0":0},1,"2",{"three":3}]', 'all', '$[0]', '$[0]."0"', '$[1]', '$[2]', '$[3]'); :: json_contains_path('[{"0":0},1,"2",{"three":3}]', 'all', '$[0]', '$[0]."0"', '$[1]', '$[2]', '$[3]') ====================================================================================================== 1 .. code-block:: sql SELECT JSON_CONTAINS_PATH ('[{"0":0},1,"2",{"three":3}]', 'all', '$[0]', '$[0]."0"', '$[1]', '$[2]', '$[3]', '$.inexistent'); :: json_contains_path('[{"0":0},1,"2",{"three":3}]', 'all', '$[0]', '$[0]."0"', '$[1]', '$[2]', '$[3]', '$.inexistent') ====================================================================================================================== 0 **JSON_CONTAINS_PATH** 함수는 json 경로 ë‚´ì— ì™€ì¼ë“œì¹´ë“œë¥¼ ì§€ì›í•œë‹¤. .. code-block:: sql SELECT JSON_CONTAINS_PATH ('[{"0":0},1,"2",{"three":3}]', 'one', '$.inexistent', '$[*]."three"'); :: json_contains_path('[{"0":0},1,"2",{"three":3}]', 'one', '$.inexistent', '$[*]."three"') ========================================================================== 1 .. _fn-json-contains: JSON_CONTAINS =================================== .. function:: JSON_CONTAINS (json_doc doc1, json_doc doc2 [, json path]) **JSON_CONTAINS** 함수는 *doc2* ê°€ 옵션으로 ì§€ì •ëœ ê²½ë¡œì˜ *doc1* ì— í¬í•¨ë˜ëŠ”ì§€ë¥¼ 검사한다. 다ìŒê³¼ ê°™ì´ ìž¬ê·€ ê·œì¹™ì´ ì¶©ì¡±ë˜ëŠ” 경우 json ìš”ì†Œì— ë‹¤ë¥¸ json 요소가 í¬í•¨ëœë‹¤. - íƒ€ìž…ì´ ê°™ê³ (**JSON_TYPE** ()ì´ ì¼ì¹˜í•˜ê³ ) 스칼ë¼ë„ ê°™ì€ ê²½ìš° json 스칼ë¼ì— 다른 json 스칼ë¼ê°€ í¬í•¨ëœë‹¤. 예외ì 으로, json integer는 **JSON_TYPE** ()ì´ ë‹¤ë¥¸ 경우ì—ë„ json doubleê³¼ 비êµë¥¼ 통해 ë™ì¼í•œ 것으로 간주ë 수 있다. - json ë°°ì—´ ìš”ì†Œì— json_nonarrayê°€ í¬í•¨ë˜ì–´ 있으면 json ë°°ì—´ì— json ìŠ¤ì¹¼ë¼ ë˜ëŠ” json ê°ì²´ê°€ í¬í•¨ëœë‹¤. - ë‘ ë²ˆì§¸ json ë°°ì—´ì˜ ëª¨ë“ ìš”ì†Œê°€ 첫 번째 json ë°°ì—´ì— í¬í•¨ë˜ì–´ 있으면 json ë°°ì—´ì— ë‹¤ë¥¸ json ë°°ì—´ì´ í¬í•¨ëœë‹¤. - ë‘ ë²ˆì§¸ ê°ì²´ì˜ ëª¨ë“ (*key2*, *value2*) ìŒì— 대해 첫 번째 ê°ì²´ì— *key1* = *key2* ì´ê³ *value2* ê°€ *value1* ì„ í¬í•¨í•˜ëŠ” (*key1*, *value1*) ìŒì´ 있는 경우 json ê°ì²´ì—는 다른 json 오브ì 트가 í¬í•¨ëœë‹¤. - ì´ ì™¸ì—는 json 요소가 í¬í•¨ë˜ì§€ 않는다. json 경로 ì¸ìžë¥¼ ìž…ë ¥í•˜ì§€ ì•Šì€ ê²½ìš° *doc2* ê°€ *doc1* ì˜ ë£¨íŠ¸ json ìš”ì†Œì— í¬í•¨ë˜ëŠ”ì§€ 여부를 반환한다. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_CONTAINS ('"simple"','"simple"'); :: json_contains('"simple"', '"simple"') ======================================= 1 .. code-block:: sql SELECT JSON_CONTAINS ('["a", "b"]','"b"'); :: json_contains('["a", "b"]', '"b"') ==================================== 1 .. code-block:: sql SELECT JSON_CONTAINS ('["a", "b1", ["a", "b2"]]','["b1", "b2"]'); :: json_contains('["a", "b1", ["a", "b2"]]','["b1", "b2"]') ========================================================== 1 .. code-block:: sql SELECT JSON_CONTAINS ('{"k1":["a", "b1"], "k2": ["a", "b2"]}','{"k1":"b1", "k2":"b2"}'); :: json_contains('{"k1":["a", "b1"], "k2": ["a", "b2"]}','{"k1":"b1", "k2":"b2"}') ================================================================================= 1 json ê°ì²´ëŠ” json ë°°ì—´ê³¼ ê°™ì€ ë°©ì‹ìœ¼ë¡œ í¬í•¨ì„ 검사하지 않으며, json ê°ì²´ì˜ 하위 ìš”ì†Œì— í¬í•¨ëœ json ê°ì²´ì˜ ìžì†ì´ 아닌 json 요소를 가질 수 없다. .. code-block:: sql SELECT JSON_CONTAINS ('["a", "b1", ["a", {"k":"b2"}]]','["b1", "b2"]'); :: json_contains('["a", "b1", ["a", {"k":"b2"}]]','["b1", "b2"]') ================================================================ 0 .. code-block:: sql SELECT JSON_CONTAINS ('["a", "b1", ["a", {"k":["b2"]}]]','["b1", {"k":"b2"}]'); :: json_contains('["a", "b1", ["a", {"k":["b2"]}]]','["b1", {"k":"b2"}]') ======================================================================== 1 .. _fn-json-merge-patch: JSON_MERGE_PATCH =================================== .. function:: JSON_MERGE_PATCH (json_doc, json_doc [, json_doc] ...) **JSON_MERGE_PATCH** 함수는 둘 ì´ìƒì˜ json 문서를 ë³‘í•©í•˜ê³ ë³‘í•©ëœ ê²°ê³¼ jsonì„ ë°˜í™˜í•œë‹¤. **JSON_MERGE_PATCH** 는 병합 ì¶©ëŒ ì‹œ ë‘ ë²ˆì§¸ ì¸ìžë¥¼ 사용하는 ì ì—서 **JSON_MERGE_PRESERVE** 와 다르다. **JSON_MERGE_PATCH** 함수는 `RFC 7396 <https://www.rfc-editor.org/info/rfc7396>` ì„ ì¤€ìˆ˜í•œë‹¤. ë‘ ê°œì˜ json 문서 ë³‘í•©ì€ ë‹¤ìŒ ê·œì¹™ì— ë”°ë¼ ìž¬ê·€ì 으로 수행ëœë‹¤: - ë‘ ê°œì˜ ë¹„ ê°ì²´ JSONì´ ë³‘í•©ë˜ë©´ 병합 결과는 ë‘ ë²ˆì§¸ ê°’ì´ë‹¤. - ê°ì²´ê°€ 아닌 jsonì´ json ê°ì²´ì™€ 병합ë˜ë©´ 빈 ê°ì²´ì™€ ë‘ ë²ˆì§¸ 병합 ì¸ìžê°€ 병합ëœë‹¤. - ë‘ ê°ì²´ê°€ 병합ë˜ë©´ ê²°ê³¼ ê°ì²´ëŠ” ë‹¤ìŒ ë©¤ë²„ë¡œ 구성ëœë‹¤: - ë‘ ë²ˆì§¸ ê°ì²´ì™€ ë™ì¼í•œ 키를 가진 멤버를 ì œì™¸í•œ 첫 번째 ê°ì²´ì˜ ëª¨ë“ ë©¤ë²„. - 첫 번째 ê°ì²´ì— ë™ì¼í•œ 키를 가진 멤버와 ëª¨ë“ ë©¤ë²„ê°€ nullì¸ ê°’ì„ ì œì™¸í•œ ë‘번째 ê°ì²´ì˜ ëª¨ë“ ë©¤ë²„. ë‘ ë²ˆì§¸ ê°ì²´ì˜ null ê°’ì„ ê°€ì§„ 멤버는 무시ëœë‹¤. - ë‘ ë²ˆì§¸ ê°ì²´ì™€ ë™ì¼í•œ 키를 가진 nullì´ ì•„ë‹Œ 첫 번째 ê°ì²´ì˜ 멤버. ë‘ ê°ì²´ 모ë‘ì— ë‚˜íƒ€ë‚˜ëŠ” ë™ì¼í•œ 키 ë©¤ë²„ì¼ ë•Œ ë‘ ë²ˆì§¸ ê°ì²´ì˜ 멤버 ê°’ì´ nullì´ë©´ 무시ëœë‹¤. ì´ ë‘ ê°œì˜ ê°’ì€ ì²« 번째 ë° ë‘ ë²ˆì§¸ ê°ì²´ì˜ 멤버 ê°’ì— ëŒ€í•´ ìˆ˜í–‰ëœ ë³‘í•©ì˜ ê²°ê³¼ê°€ ëœë‹¤. 병합 ìž‘ì—…ì€ ë‘ ê°œ ì´ìƒì˜ ì¸ìžê°€ ìžˆì„ ë•Œ ì—°ì†ì 으로 실행ëœë‹¤. ì²˜ìŒ ë‘ ì¸ìžë¥¼ 병합한 결과는 세 번째와 병합ë˜ê³ ì´ ê²°ê³¼ëŠ” 네 번째와 병합ëœë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_MERGE_PATCH ('["a","b","c"]', '"scalar"'); :: json_merge_patch('["a","b","c"]', '"scalar"') ====================== "scalar" 첫 번째 ì¸ìžê°€ ê°ì²´ê°€ ì•„ë‹ˆê³ ë‘ ë²ˆì§¸ ì¸ìžê°€ ê°ì²´ ì¸ ê²½ìš° ë³‘í•©ì— ëŒ€í•œ 예외. 빈 ê°ì²´ì™€ ë‘ ë²ˆì§¸ ê°ì²´ ì¸ìž ê°„ì— ë³‘í•© ìž‘ì—…ì´ ìˆ˜í–‰ëœë‹¤. .. code-block:: sql SELECT JSON_MERGE_PATCH ('["a"]', '{"a":null}'); :: json_merge_patch('["a"]', '{"a":null}') ====================== {} ê¸°ìˆ ëœ ê°ì²´ 병합 예시: .. code-block:: sql SELECT JSON_MERGE_PATCH ('{"a":null,"c":["elem"]}','{"b":null,"c":{"k":null},"d":"elem"}'); :: json_merge_patch('{"a":null,"c":["elem"]}', '{"b":null,"c":{"k":null},"d":"elem"}') ====================== {"a":null,"c":{},"d":"elem"} .. _fn-json-merge-preserve: JSON_MERGE_PRESERVE =================================== .. function:: JSON_MERGE_PRESERVE (json_doc, json_doc [, json_doc] ...) **JSON_MERGE_PRESERVE** 함수는 둘 ì´ìƒì˜ json 문서를 ë³‘í•©í•˜ê³ ë³‘í•©ëœ ê²°ê³¼ jsonì„ ë°˜í™˜í•œë‹¤. **JSON_MERGE_PRESERVE** 는 병합 ì¶©ëŒ ì‹œ ë‘ json 요소를 ëª¨ë‘ ë³´ì¡´í•œë‹¤ëŠ” ì ì—서 **JSON_MERGE_PATCH** 와 다르다. ë‘ json ë¬¸ì„œì˜ ë³‘í•©ì€ ë‹¤ìŒ ê·œì¹™ì— ë”°ë¼ ìž¬ê·€ì 으로 수행ëœë‹¤: - ë‘ ê°œì˜ json ë°°ì—´ì´ ë³‘í•©ë˜ë©´ ì—°ê²°ëœë‹¤. - ë‘ ê°œì˜ ë¹„ ë°°ì—´ (ìŠ¤ì¹¼ë¼ / 오브ì 트) json 요소가 병합ë˜ê³ ê·¸ 중 하나만 json ê°ì²´ì¸ 경우 결과는 ë‘ ê°œì˜ json 요소를 í¬í•¨í•˜ëŠ” ë°°ì—´ì´ë‹¤. - 비 ë°°ì—´ json 요소가 json ë°°ì—´ê³¼ 병합ë˜ë©´ 비 ë°°ì—´ì€ ë‹¨ì¼ ìš”ì†Œ json 배열로 ë³€ê²½ëœ ë‹¤ìŒ json ë°°ì—´ 병합 ê·œì¹™ì— ë”°ë¼ json ë°°ì—´ê³¼ 병합ëœë‹¤. - ë‘ ê°œì˜ json ê°ì²´ê°€ 병합ë˜ë©´ 다른 json ê°ì²´ì™€ 비êµí•´ 없는 ëª¨ë“ ë©¤ë²„ê°€ ìœ ì§€ëœë‹¤. ì¼ì¹˜í•˜ëŠ” í‚¤ì˜ ê²½ìš° ê·œì¹™ì„ ìž¬ê·€ì 으로 ì 용하여 ê°’ì´ í•ìƒ ë³‘í•©ëœë‹¤. 병합 ìž‘ì—…ì€ ë‘ ê°œ ì´ìƒì˜ ì¸ìžê°€ ìžˆì„ ë•Œ ì—°ì†ì 으로 실행ëœë‹¤. ì²˜ìŒ ë‘ ì¸ìžë¥¼ 병합 한 결과는 세 번째와 병합ë˜ê³ ì´ ê²°ê³¼ëŠ” 네 번째와 병합ëœë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_MERGE_PRESERVE ('"a"', '"b"'); :: json_merge('"a"', '"b"') ====================== ["a","b"] .. code-block:: sql SELECT JSON_MERGE_PRESERVE ('["a","b","c"]', '"scalar"'); :: json_merge('["a","b","c"]', '"scalar"') ====================== ["a","b","c","scalar"] **JSON_MERGE_PATCH** 와 달리 **JSON_MERGE_PRESERVE** 는 병합하는 ë™ì•ˆ 첫 번째 ì¸ìžì˜ 요소를 ì‚ì œ ë° ìˆ˜ì •í•˜ì§€ ì•Šê³ í•©ì³ì„œ ê°€ì ¸ì˜¨ë‹¤. .. code-block:: sql SELECT JSON_MERGE_PRESERVE ('{"a":null,"c":["elem"]}','{"b":null,"c":{"k":null},"d":"elem"}'); :: json_merge('{"a":null,"c":["elem"]}','{"b":null,"c":{"k":null},"d":"elem"}') ====================== {"a":null,"c":["elem",{"k":null}],"b":null,"d":"elem"} .. _fn-json-merge: JSON_MERGE =================================== .. function:: JSON_MERGE (json_doc, json_doc [, json_doc] ...) **JSON_MERGE** 는 **JSON_MERGE_PRESERVE** ì˜ ë³„ì¹ì´ë‹¤. .. _fn-json-array-append: JSON_ARRAY_APPEND =================================== .. function:: JSON_ARRAY_APPEND (json_doc, json path, json_val [, json path, json_val] ...) **JSON_ARRAY_APPEND** 함수는 첫 번째 ì¸ìžì˜ ìˆ˜ì •ëœ ì‚¬ë³¸ì„ ë°˜í™˜í•œë‹¤. 주어진 ê° <*json path*, *json_val*> ì— ëŒ€í•´ 함수는 해당 경로로 ì§€ì •ëœ json ë°°ì—´ì— ê°’ì„ ì¶”ê°€í•œë‹¤. (*json path*, *json_val*) ì€ ì™¼ìª½ì—서 오른쪽으로 하나씩 í‰ê°€í•œë‹¤. 한 ìŒì„ í‰ê°€í•˜ì—¬ ìž‘ì„±ëœ ë¬¸ì„œëŠ” ë‹¤ìŒ ìŒì„ í‰ê°€í•˜ëŠ” 새로운 ê°’ì´ ëœë‹¤. json 경로가 *json_doc* ë‚´ë¶€ì˜ json ë°°ì—´ì„ ê°€ë¦¬í‚¤ëŠ” 경우 *json_val* ì´ ë°°ì—´ì˜ ëì— ì¶”ê°€ëœë‹¤. json 경로가 비 ë°°ì—´ json 요소를 ì§€ì •í•˜ëŠ” 경우 비 ë°°ì—´ 요소를 í¬í•¨í•˜ëŠ” ë‹¨ì¼ ìš”ì†Œ json 배열로 변경ë˜ê³ *json_val* ì„ ì¶”ê°€í•œë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_ARRAY_APPEND ('{"a":[1,2]}','$.a','b'); :: json_array_append('{"a":[1,2]}', '$.a', 'b') ====================== {"a":[1,2,"b"]} .. code-block:: sql SELECT JSON_ARRAY_APPEND ('{"a":1}','$.a','b'); :: json_array_append('{"a":1}', '$.a', 'b') ====================== {"a":[1,"b"]} .. code-block:: sql SELECT JSON_ARRAY_APPEND ('{"a":[1,2]}', '$.a[0]', '1'); :: json_array_append('{"a":[1,2]}', '$.a[0]', '1') ====================== {"a":[[1,"1"],2]} .. _fn-json-array-insert: JSON_ARRAY_INSERT =================================== .. function:: JSON_ARRAY_INSERT (json_doc, json path, json_val [, json path, json_val] ...) **JSON_ARRAY_INSERT** 함수는 첫 번째 ì¸ìžì˜ ìˆ˜ì •ëœ ì‚¬ë³¸ì„ ë°˜í™˜í•œë‹¤. 주어진 ê° <*json path*, *json_val*> ì— ëŒ€í•´ 함수는 해당 경로로 ì§€ì •ëœ json ë°°ì—´ì— ê°’ì„ ì‚½ìž…í•œë‹¤. (*json path*, *json_val*) ì€ ì™¼ìª½ì—서 오른쪽으로 하나씩 í‰ê°€í•œë‹¤. 한 ìŒì„ í‰ê°€í•˜ì—¬ ìž‘ì„±ëœ ë¬¸ì„œëŠ” ë‹¤ìŒ ìŒì„ í‰ê°€í•˜ëŠ” 새로운 ê°’ì´ ëœë‹¤. **JSON_ARRAY_INSERT** ìž‘ì—…ì˜ ê·œì¹™ì€ ë‹¤ìŒê³¼ 같다: - json 경로가 json_arrayì˜ ìš”ì†Œë¥¼ ì§€ì •í•˜ë©´ *json_val* ì´ ì§€ì •ëœ ìƒ‰ì¸ì— 삽입ë˜ì–´ ë‹¤ìŒ ìš”ì†Œë¥¼ 오른쪽으로 ì´ë™ì‹œí‚¨ë‹¤. - json 경로가 ë°°ì—´ ëì˜ ë‹¤ìŒì„ 가리키는 경우, ë°°ì—´ì˜ ë부터 ì§€ì •ëœ ìƒ‰ì¸ì— 삽입ë 때까지 null로 채워진다. ê·¸ë¦¬ê³ json_valì´ ì§€ì •ëœ ìƒ‰ì¸ì— 삽입ëœë‹¤. - json 경로가 *json_doc* ë‚´ì— ì¡´ìž¬í•˜ì§€ 않는 경우, json ê²½ë¡œì˜ ë§ˆì§€ë§‰ í† í°ì€ ë°°ì—´ ì¸ë±ìФì´ê³ 마지막 ë°°ì—´ ì¸ë±ìФ í† í°ì´ 없는 json 경로는 *json_doc* ë‚´ì˜ ìš”ì†Œë¥¼ ì§€ì •í–ˆì„ ê²ƒì´ë‹¤. 마지막 í† í°ì„ ì œì™¸í•œ json 경로로 ì°¾ì€ ìš”ì†ŒëŠ” ë‹¨ì¼ ìš”ì†Œ json 배열로 대체ë˜ê³ **JSON_ARRAY_INSERT** ìž‘ì—…ì€ ì›ëž˜ json 경로로 수행ëœë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ 않거나 *json_path* ê°€ *json_doc* ë‚´ë¶€ì˜ ë°°ì—´ì˜ ìž¥ì†Œë¥¼ ì§€ì •í•˜ì§€ 않으면 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_ARRAY_INSERT ('[0,1,2]', '$[0]', '1'); :: json_array_insert('[0,1,2]', '$[0]', '1') ====================== ["1",0,1,2] .. code-block:: sql SELECT JSON_ARRAY_INSERT ('[0,1,2]', '$[5]', '1'); :: json_array_insert('[0,1,2]', '$[5]', '1') ====================== [0,1,2,null,null,"1"] Examples for **JSON_ARRAY_INSERT's** third rule. .. code-block:: sql SELECT JSON_ARRAY_INSERT ('{"a":4}', '$[5]', '1'); :: json_array_insert('{"a":4}', '$[5]', '1') ====================== [{"a":4},null,null,null,null,"1"] .. code-block:: sql SELECT JSON_ARRAY_INSERT ('"a"', '$[5]', '1'); :: json_array_insert('"a"', '$[5]', '1') ====================== ["a",null,null,null,null,"1"] .. _fn-json-insert: JSON_INSERT =================================== .. function:: JSON_INSERT (json_doc, json path, json_val [, json path, json_val] ...) **JSON_INSERT** 함수는 첫 번째 ì¸ìžì˜ ìˆ˜ì •ëœ ì‚¬ë³¸ì„ ë°˜í™˜í•œë‹¤. 주어진 ê° <*json path*, *json_val*> ì— ëŒ€í•´ 해당 ê²½ë¡œì— ë‹¤ë¥¸ ê°’ì´ ì—†ìœ¼ë©´ ê°’ì„ ì‚½ìž…í•œë‹¤. **JSON_INSERT** ì˜ ì‚½ìž… ê·œì¹™ì€ ë‹¤ìŒê³¼ 같다: json 경로가 *json_doc* ë‚´ì˜ ë‹¤ìŒ json ê°’ 중 하나를 처리하는 경우 *json_val* ì´ ì‚½ìž…ëœë‹¤: - 기존 json ê°ì²´ì— 존재하지 않는 ê°ì²´ 멤버ì´ë‹¤. 키(key)ê°€ json ê²½ë¡œì˜ ë§ˆì§€ë§‰ 요소ì´ê³ ê°’ì´ *json_val* ì¸ (*key*, *value*)ì´ json 오브ì íŠ¸ì— ì¶”ê°€ëœë‹¤. - 기존 json ë°°ì—´ ëì„ ë„˜ëŠ” ë°°ì—´ 색ì¸. ë°°ì—´ì€ ë°°ì—´ì˜ ë까지 ë„로 ì±„ì›Œì§€ê³ *json_val* ì€ ì§€ì •ëœ ìƒ‰ì¸ì— 삽입ëœë‹¤. <*json path*, *json_val*> 한 ìŒì„ í‰ê°€í•˜ì—¬ ìž‘ì„±ëœ json_docì€ ë‹¤ìŒ <*json path*, *json_val*>ì´ í‰ê°€ë 때 새로운 ê°’ì´ ëœë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류가 ë°œìƒí•œë‹¤. * json_doc * ë‚´ì˜ ê¸°ì¡´ ìš”ì†Œì— ëŒ€í•œ 경로는 무시ëœë‹¤: .. code-block:: sql SELECT JSON_INSERT ('{"a":1}','$.a','b'); :: json_insert('{"a":1}', '$.a', 'b') ====================== {"a":1} .. code-block:: sql SELECT JSON_INSERT ('{"a":1}','$.b','1'); :: json_insert('{"a":1}', '$.b', '1') ====================== {"a":1,"b":"1"} .. code-block:: sql SELECT JSON_INSERT ('[0,1,2]','$[4]','1'); :: json_insert('[0,1,2]', '$[4]', '1') ====================== [0,1,2,null,"1"] .. _fn-json-set: JSON_SET =================================== .. function:: JSON_SET (json_doc, json path, json_val [, json path, json_val] ...) **JSON_SET** 함수는 첫 번째 ì¸ìžì˜ ìˆ˜ì •ëœ ì‚¬ë³¸ì„ ë°˜í™˜í•œë‹¤. 주어진 ê° <*json path*, *json_val*> ì— ëŒ€í•´ 함수는 해당 ê²½ë¡œì˜ ê°’ì„ ì‚½ìž…í•˜ê±°ë‚˜ 대체한다. json 경로가 *json_doc* ë‚´ë¶€ì—서 ì•„ëž˜ì˜ json ê°’ 중 하나를 ì§€ì •í•˜ë©´ *json_val* ì´ ì‚½ìž…ëœë‹¤. - 기존 json ê°ì²´ì˜ 존재하지 않는 ê°ì²´ 멤버. (*key*, *value*) ì´ json 경로ì—서 ì¶”ë¡ ëœ í‚¤ì™€ *json_val* 값으로 json ê°ì²´ì— 추가ëœë‹¤. - 기존 json ë°°ì—´ ëì„ ë„˜ëŠ” ë°°ì—´ 색ì¸. ë°°ì—´ì€ ë°°ì—´ì˜ ë까지 ë„로 ì±„ì›Œì§€ê³ *json_val* ì€ ì§€ì •ëœ ìƒ‰ì¸ì— 삽입ëœë‹¤. <*json path*, *json_val*> 한 ìŒì„ í‰ê°€í•˜ì—¬ ìž‘ì„±ëœ json_docì€ ë‹¤ìŒ <*json path*, *json_val*>ì´ í‰ê°€ë 때 새로운 ê°’ì´ ëœë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_SET ('{"a":1}','$.a','b'); :: json_set('{"a":1}', '$.a', 'b') ====================== {"a":"b"} .. code-block:: sql SELECT JSON_SET ('{"a":1}','$.b','1'); :: json_set('{"a":1}', '$.b', '1') ====================== {"a":1,"b":"1"} .. code-block:: sql SELECT JSON_SET ('[0,1,2]','$[4]','1'); :: json_set('[0,1,2]', '$[4]', '1') ====================== [0,1,2,null,"1"] .. _fn-json-replace: JSON_REPLACE =================================== .. function:: JSON_REPLACE (json_doc, json path, json_val [, json path, json_val] ...) **JSON_REPLACE** 함수는 첫 번째 ì¸ìžì˜ ìˆ˜ì •ëœ ì‚¬ë³¸ì„ ë°˜í™˜í•œë‹¤. 주어진 ê° <*json path*, *json_val*> ì— ëŒ€í•´ 해당 ê²½ë¡œì— ë‹¤ë¥¸ ê°’ì´ ìžˆëŠ” 경우ì—ë§Œ ê°’ì„ ëŒ€ì²´í•œë‹¤. *json_path* ê°€ *json_doc* ë‚´ì— ì¡´ìž¬í•˜ì§€ 않으면 (*json path*, *json_val*) ì´ ë¬´ì‹œë˜ê³ 변경ë˜ì§€ 않는다. <*json path*, *json_val*> 한 ìŒì„ í‰ê°€í•˜ì—¬ ìž‘ì„±ëœ json_docì€ ë‹¤ìŒ <*json path*, *json_val*>ì´ í‰ê°€ë 때 새로운 ê°’ì´ ëœë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ ì•Šì€ ê²½ìš° 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_REPLACE ('{"a":1}','$.a','b'); :: json_replace('{"a":1}', '$.a', 'b') ====================== {"a":"b"} *json_doc* ì•ˆì— *json path* ê°€ 없으면 대체 (replace) ë™ìž‘ì´ ìˆ˜í–‰ë˜ì§€ 않는다. .. code-block:: sql SELECT JSON_REPLACE ('{"a":1}','$.b','1'); :: json_replace('{"a":1}', '$.b', '1') ====================== {"a":1} .. code-block:: sql SELECT JSON_REPLACE ('[0,1,2]','$[4]','1'); :: json_replace('[0,1,2]', '$[4]', '1') ====================== [0,1,2] .. _fn-json-remove: JSON_REMOVE =================================== .. function:: JSON_REMOVE (json_doc, json path [, json path] ...) **JSON_REMOVE** 함수는 주어진 ëª¨ë“ ê²½ë¡œì—서 ê°’ì„ ì œê±°í•˜ì—¬ 첫 번째 ì¸ìžì˜ ìˆ˜ì •ëœ ì‚¬ë³¸ì„ ë°˜í™˜í•œë‹¤. json 경로 ì¸ìžëŠ” 왼쪽ì—서 오른쪽으로 하나씩 í‰ê°€ëœë‹¤. json 경로를 í‰ê°€í•˜ì—¬ ìƒì„±ëœ 결과는 ë‹¤ìŒ json 경로가 í‰ê°€ë˜ëŠ” ê°’ì´ ëœë‹¤. ì¸ìžê°€ **NULL** ì´ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. ì¸ìžê°€ ìœ íš¨í•˜ì§€ 않거나 경로가 루트를 ì§€ì •í•˜ê±°ë‚˜ 경로가 없는 경우 오류가 ë°œìƒí•œë‹¤. .. code-block:: sql SELECT JSON_REMOVE ('[0,1,2]','$[1]'); :: json_remove('[0,1,2]','$[1]') ====================== [0,2] .. code-block:: sql SELECT JSON_REMOVE ('{"a":1,"b":2}','$.a'); :: json_remove('{"a":1,"b":2}','$.a') ====================== {"b":2} .. _fn-json-table: JSON_TABLE ===================== **JSON_TABLE** 함수는 jsonì„ ì¼ë°˜ í…Œì´ë¸”ê³¼ ìœ ì‚¬í•˜ê²Œ 질ì˜(query)í• ìˆ˜ 있는 ìœ ì‚¬ í…Œì´ë¸” 구조로 변환하는 ê²ƒì„ ìš©ì´í•˜ê²Œ 해준다. ë³€í™˜ì€ ì˜ˆë¥¼ 들면 JSON_ARRAY 요소를 확장함으로ì¨, í•˜ë‚˜ì˜ í–‰ ë˜ëŠ” ë³µìˆ˜ì˜ í–‰ì„ ìƒì„±í•œë‹¤. **JSON_TABLE** ì˜ ì „ì²´ 문법 : :: JSON_TABLE( expr, path COLUMNS (column_list) ) [AS] alias <column_list>::= <column> [, <column>] ... <column>::= name FOR ORDINALITY | name type PATH string_path <on_empty> <on_error> | name type EXISTS PATH string_path | NESTED [PATH] string_path COLUMNS <column_list> <on_empty>::= NULL | ERROR | DEFAULT value ON EMPTY <on_error>::= NULL | ERROR | DEFAULT value ON ERROR *json_doc* exprì€ ê²°ê³¼ê°€ json_docì´ ë˜ëŠ” 표현ì‹ì´ì–´ì•¼ 한다. ìƒìˆ˜ json, í…Œì´ë¸”ì˜ ì—´ ë˜ëŠ” 함수 ë˜ëŠ” ì—°ì‚°ìžì˜ ê²°ê³¼ ì¼ ìˆ˜ 있다. *json path* 는 ìœ íš¨í•œ 경로 ì´ì–´ì•¼ 하며 **COLUMNS** ì ˆì—서 í‰ê°€í• json ë°ì´í„°ë¥¼ 추출하는 ë° ì‚¬ìš©ëœë‹¤. ** COLUMNS ** ì ˆì€ ì—´ ìœ í˜• ë° ì¶œë ¥ì„ ì–»ê¸° 위해 수행ë˜ëŠ” ìž‘ì—…ì„ ì •ì˜í•œë‹¤. [**AS**] *alias* ì ˆì´ í•„ìš”í•˜ë‹¤. **JSON_TABLE** ì€ ë„¤ 가지 ìœ í˜•ì˜ ì—´ì„ ì§€ì›í•œë‹¤: - *name* **FOR ORDINALITY** : ì´ ìœ í˜•ì€ **COLUMNS** ì ˆ ë‚´ì—서 í–‰ 번호를 ì¶”ì 한다. ì—´ ìœ í˜•ì€ **INTEGER** ì´ë‹¤. - *name* *type* **PATH** *json path* [**on empty**] [**on error**] :ì´ ìœ í˜•ì˜ ì—´ì€ ì§€ì •ëœ json 경로ì—서 json_values를 추출하는 ë° ì‚¬ìš©ëœë‹¤. ì¶”ì¶œëœ json ë°ì´í„°ëŠ” ì§€ì •ëœ ìœ í˜•ìœ¼ë¡œ ê°•ì œ 변환ëœë‹¤. 경로가 존재하지 않으면 **on empty** ì ˆì´ ìžë™ 수행ëœë‹¤. ì¶”ì¶œëœ json ê°’ì´ ëŒ€ìƒ ìœ í˜•ìœ¼ë¡œ 변환ë˜ì§€ 않으면 **on error** ì ˆì´ ìžë™ 수행ëœë‹¤. - **on empty**\ì€ ê²½ë¡œê°€ 존재하지 않는 경우 **JSON_TABLE**\ì˜ ë™ìž‘ì„ ê²°ì •í•œë‹¤. **on empty**\ì€ ë‹¤ìŒ ê°’ 중 하나를 가질 수 있다: - **NULL ON EMPTY** : ì—´ì´ **NULL** 로 ì„¤ì •ëœë‹¤. ì´ê²ƒì´ 기본 ë™ìž‘ì´ë‹¤. - **ERROR ON EMPTY**: 오류가 ë°œìƒí•œë‹¤. - **DEFAULT** *value* **ON EMPTY**: 빈 ê°’ ëŒ€ì‹ ì— *value* ê°€ 사용ëœë‹¤. - **on error** 는 ë‹¤ìŒ ê°’ 중 하나를 가질 수 있다.: - **NULL ON ERROR**: ì—´ì´ **NULL** 로 ì„¤ì •ëœë‹¤. ì´ê²ƒì´ 기본 ë™ìž‘ì´ë‹¤. - **ERROR ON ERROR**: 오류가 ë°œìƒí•œë‹¤. - **DEFAULT** *value* **ON ERROR**: ì›í•˜ëŠ” ì—´ ìœ í˜•ìœ¼ë¡œ ê°•ì œ 변환하지 못한 ë°°ì—´ / ê°ì²´ / json ìŠ¤ì¹¼ë¼ ëŒ€ì‹ *value* ê°€ 사용ëœë‹¤. - *name* *type* **EXISTS PATH** *json path*: json 경로 ìœ„ì¹˜ì— ë°ì´í„°ê°€ 있으면 1ì„ ë°˜í™˜í•˜ê³ ê·¸ë ‡ì§€ 않으면 0ì„ ë°˜í™˜í•œë‹¤. - **NESTED** [**PATH**] *json path* **COLUMNS** (*column list*) 는 경로ì—서 ì°¾ì€ json ë°ì´í„°ì—서 부모 결과와 ê²°í•© ëœ í–‰ê³¼ ì—´ì˜ ê°œë³„ 서브 세트를 ìƒì„±í•œë‹¤. \ \결과는 "for each"루프와 ìœ ì‚¬í•˜ê²Œ ê²°í•©ëœë‹¤. \ \json 경로는 부모 경로와 ê´€ë ¨ì´ ìžˆë‹¤. \ \ **COLUMNS** ì ˆì— ëŒ€í•´ ë™ì¼í•œ ê·œì¹™ì´ ìž¬ê·€ì 으로 ì ìš©ëœë‹¤. .. code-block:: sql SELECT * FROM JSON_TABLE ( '{"a":[1,[2,3]]}', '$.a[*]' COLUMNS ( col INT PATH '$') ) AS jt; :: col ====================== 1 -- first value found at '$.a[*]' is 1 json scalar, which is coercible to 1 NULL -- second value found at '$.a[*]' is [2,3] json array which cannot be coerced to int, triggering NULL ON ERROR default behavior 기본 on_error ë™ìž‘ì„ ìž¬ì •ì˜í•˜ë©´ ì´ì „ ì˜ˆì œì™€ 다른 결과가 나타난다: .. code-block:: sql SELECT * FROM JSON_TABLE ( '{"a":[1,[2,3]]}', '$.a[*]' COLUMNS ( col INT PATH '$' DEFAULT '-1' ON ERROR) ) AS jt; :: col ====================== 1 -- first value found at '$.a[*]' is '1' json scalar, which is coercible to 1 -1 -- second value found at '$.a[*]' is '[2,3]' json array which cannot be coerced to int, triggering ON ERROR **ON EMPTY** example: .. code-block:: sql SELECT * FROM JSON_TABLE ( '{"a":1}', '$' COLUMNS ( col1 INT PATH '$.a', col2 INT PATH '$.b', col3 INT PATH '$.c' DEFAULT '0' ON EMPTY) ) AS jt; :: col1 col2 col3 ======================================= 1 NULL 0 아래 예ì—서 '$. *'경로는 ìƒìœ„ ì—´ì´ ë£¨íŠ¸ json ê°ì²´ì˜ 멤버 ê°’ì„ í•˜ë‚˜ì”© ë°›ë„ë¡ í•˜ëŠ” ë° ì‚¬ìš©ëœë‹¤. ì—´ a는 ì²˜ë¦¬ëœ ë‚´ìš©ì„ ë³´ì—¬ì¤€ë‹¤. 그런 ë‹¤ìŒ ë£¨íŠ¸ 오브ì íŠ¸ì˜ ê° ë©¤ë²„ ê°’ì€ **NESTED** [**PATH**] ì ˆì— ì˜í•´ 추가로 처리ëœë‹¤. **NESTED PATH**\는 경로 '$ [*]'를 사용하여 ë°°ì—´ì˜ ê° ìš”ì†Œë¥¼ ì—´ì— ì˜í•´ 추가로 처리한다. **FOR ORDINALITY** ì—´ì€ í˜„ìž¬ ì²˜ë¦¬ëœ ìš”ì†Œì˜ ìˆ˜ë¥¼ ì¶”ì 한다. ì˜ˆì œ ê²°ê³¼ì—서 우리는 ì—´ì˜ ê° ìƒˆë¡œìš´ ìš”ì†Œì— ëŒ€í•´ * ord * ì—´ì˜ ê°’ë„ ì¦ê°€í•¨ì„ 알 수 있다. **FOR ORDINALITY** *nested_ord* ì—´ì€ í˜•ì œ ì—´(sibling columns)ì— ì˜í•´ 처리ë˜ëŠ” 요소 ìˆ˜ì˜ ì¹´ìš´í„° ì—í• ë„ í•œë‹¤. ì¤‘ì²©ëœ **FOR ORDINALITY** ì—´ì€ ê° ì¼ê´„ 처리가 ì™„ë£Œëœ í›„ ìž¬ì„¤ì •ëœë‹¤. 세 번째 ë©¤ë²„ì˜ ê°’ì¸ 6ì€ ë°°ì—´ë¡œ 취급ë 수 없으므로 ì¤‘ì²©ëœ ì—´ë¡œ ì²˜ë¦¬í• ìˆ˜ 없다. ì¤‘ì²©ëœ ì—´ì€ **NULL** ê°’ì„ ìƒì„±í•œë‹¤. .. code-block:: sql SELECT * FROM JSON_TABLE ( '{"a":[1,2],"b":[3,4,5],"d":6,"c":[7]}', '$.*' COLUMNS ( ord FOR ORDINALITY, col JSON PATH '$', NESTED PATH '$[*]' COLUMNS ( nested_ord FOR ORDINALITY, nested_col JSON PATH '$')) ) AS jt; :: ord col nested_ord nested_col ===================================================================== 1 [1,2] 1 1 1 [1,2] 2 2 2 [3,4,5] 1 3 2 [3,4,5] 2 4 2 [3,4,5] 3 5 3 6 NULL NULL 4 [7] 1 7 ë‹¤ìŒ ì˜ˆëŠ” 여러 ê°œì˜ ë™ì¼í•œ ë ˆë²¨ **NESTED** [**PATH**] ì ˆì´ **JSON_TABLE** ì— ì˜í•´ 처리ë˜ëŠ” ë°©ë²•ì„ ë³´ì—¬ì¤€ë‹¤. 처리ë ê°’ì€ ê° **NESTED** [**PATH**] ì ˆì— í•˜ë‚˜ì”© 차례로 순서대로 ì „ë‹¬ëœë‹¤. **NESTED** [**PATH**] ì ˆë¡œ ê°’ì„ ì²˜ë¦¬í•˜ëŠ” ë™ì•ˆ í˜•ì œ **NESTED** [**PATH**] ì ˆì€ **NULL** 값으로 ì—´ì„ ì±„ìš´ë‹¤. .. code-block:: sql SELECT * FROM JSON_TABLE ( '{"a":{"key1":[1,2], "key2":[3,4,5]},"b":{"key1":6, "key2":[7]}}', '$.*' COLUMNS ( ord FOR ORDINALITY, col JSON PATH '$', NESTED PATH '$.key1[*]' COLUMNS ( nested_ord1 FOR ORDINALITY, nested_col1 JSON PATH '$'), NESTED PATH '$.key2[*]' COLUMNS ( nested_ord2 FOR ORDINALITY, nested_col2 JSON PATH '$')) ) AS jt; :: ord col nested_ord1 nested_col1 nested_ord2 nested_col2 =================================================================================================================== 1 {"key1":[1,2],"key2":[3,4,5]} 1 1 NULL NULL 1 {"key1":[1,2],"key2":[3,4,5]} 2 2 NULL NULL 1 {"key1":[1,2],"key2":[3,4,5]} NULL NULL 1 3 1 {"key1":[1,2],"key2":[3,4,5]} NULL NULL 2 4 1 {"key1":[1,2],"key2":[3,4,5]} NULL NULL 3 5 2 {"key1":6,"key2":[7]} NULL NULL 1 7 An example for multiple layers **NESTED** [**PATH**] clauses: .. code-block:: sql SELECT * FROM JSON_TABLE ( '{"a":{"key1":[1,2], "key2":[3,4,5]},"b":{"key1":6, "key2":[7]}}', '$.*' COLUMNS ( ord FOR ORDINALITY, col JSON PATH '$', NESTED PATH '$.*' COLUMNS ( nested_ord1 FOR ORDINALITY, nested_col1 JSON PATH '$', NESTED PATH '$[*]' COLUMNS ( nested_ord11 FOR ORDINALITY, nested_col11 JSON PATH '$')), NESTED PATH '$.key2[*]' COLUMNS ( nested_ord2 FOR ORDINALITY, nested_col2 JSON PATH '$')) ) AS jt; :: ord col nested_ord1 nested_col1 nested_ord11 nested_col11 nested_ord2 nested_col2 ======================================================================================================================================================= 1 {"key1":[1,2],"key2":[3,4,5]} 1 [1,2] 1 1 NULL NULL 1 {"key1":[1,2],"key2":[3,4,5]} 1 [1,2] 2 2 NULL NULL 1 {"key1":[1,2],"key2":[3,4,5]} 2 [3,4,5] 1 3 NULL NULL 1 {"key1":[1,2],"key2":[3,4,5]} 2 [3,4,5] 2 4 NULL NULL 1 {"key1":[1,2],"key2":[3,4,5]} 2 [3,4,5] 3 5 NULL NULL 1 {"key1":[1,2],"key2":[3,4,5]} NULL NULL NULL NULL 1 3 1 {"key1":[1,2],"key2":[3,4,5]} NULL NULL NULL NULL 2 4 1 {"key1":[1,2],"key2":[3,4,5]} NULL NULL NULL NULL 3 5 2 {"key1":6,"key2":[7]} 1 6 NULL NULL NULL NULL 2 {"key1":6,"key2":[7]} 2 [7] 1 7 NULL NULL 2 {"key1":6,"key2":[7]} NULL NULL NULL NULL 1 7