Индекс в функции JSON_EXTRACT не возвращает данные

#mysql #json

#mysql #json

Вопрос:

моя проблема в том, что когда я пытаюсь взять данные с помощью функции mysql JSON_EXTRACT, дело в том, что я делаю с индексом [0], и все работает нормально, но когда я запрашиваю следующий [1], возвращает null . Я пытался без индекса узнать, как искать, и это вернуло все мои данные json, и когда я попытался занять индексированную позицию поверх позиции 0, не возвращает никаких данных, только null. Вот мой пример кода:

 set @example = '{"product":{
                            "id_product":1, 
                            "quantity":1
                           },
                 "product":{
                            "id_product":3, 
                            "quantity":4
                            },
                 "product":{
                            "id_product":5, 
                            "quantity":2
                            }
                 }';

select JSON_EXTRACT(@example, '$.product[0].id_product'); -- Returns '1'
select JSON_EXTRACT(@example, '$.product[1].id_product'); -- Returns null, should be '3'
 

Я хотел бы знать, как именно это работает, если на самом деле это не так.
Заранее спасибо.

Ответ №1:

Выигрывает последний дубликат ключа.

11.6 Тип данных JSON :: Нормализация, объединение и автоматическое преобразование значений JSON

Это поведение «выигрывает последний дубликат ключа» предложено RFC 7159 и реализовано большинством анализаторов JavaScript.

В версиях MySQL до версии 8.0.3 элементы с ключами, которые дублировали ключ, найденный ранее в документе, были отброшены.

Пример:

 mysql> SELECT VERSION();
 ----------- 
| VERSION() |
 ----------- 
| 8.0.15    |
 ----------- 
1 row in set (0.00 sec)

mysql> SET @`example` := '{
    '>   "product": {
    '>     "id_product": 1,
    '>     "quantity": 1
    '>   },
    '>   "product": {
    '>     "id_product": 3,
    '>     "quantity": 4
    '>   },
    '>   "product": {
    '>     "id_product": 5,
    '>     "quantity": 2
    '>   }
    '> }';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT JSON_VALID(@`example`);
 ------------------------ 
| JSON_VALID(@`example`) |
 ------------------------ 
|                      1 |
 ------------------------ 
1 row in set (0.01 sec)

mysql> SELECT JSON_LENGTH(@`example`);
 ------------------------- 
| JSON_LENGTH(@`example`) |
 ------------------------- 
|                       1 |
 ------------------------- 
1 row in set (0.00 sec)

mysql> SELECT JSON_EXTRACT(@`example`, '$.product');
 --------------------------------------- 
| JSON_EXTRACT(@`example`, '$.product') |
 --------------------------------------- 
| {"quantity": 2, "id_product": 5}      |
 --------------------------------------- 
1 row in set (0.00 sec)
 

Некоторые параметры

Вариант 0:

 mysql> SET @`example` := '{
    '>   "product_0": {
    '>     "id_product": 1,
    '>     "quantity": 1
    '>   },
    '>   "product_1": {
    '>     "id_product": 3,
    '>     "quantity": 4
    '>   },
    '>   "product_2": {
    '>     "id_product": 5,
    '>     "quantity": 2
    '>   }
    '> }';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT JSON_VALID(@`example`);
 ------------------------ 
| JSON_VALID(@`example`) |
 ------------------------ 
|                      1 |
 ------------------------ 
1 row in set (0.00 sec)

mysql> SELECT JSON_LENGTH(@`example`);
 ------------------------- 
| JSON_LENGTH(@`example`) |
 ------------------------- 
|                       3 |
 ------------------------- 
1 row in set (0.00 sec)

mysql> SELECT
    ->   JSON_EXTRACT(@`example`, '$.product_0.id_product'),
    ->   JSON_EXTRACT(@`example`, '$.product_1.id_product'),
    ->   JSON_EXTRACT(@`example`, '$.product_2.id_product')G
*************************** 1. row ***************************
JSON_EXTRACT(@`example`, '$.product_0.id_product'): 1
JSON_EXTRACT(@`example`, '$.product_1.id_product'): 3
JSON_EXTRACT(@`example`, '$.product_2.id_product'): 5
1 row in set (0.00 sec)
 

Вариант 1:

 mysql> SET @`example` := '[
    '> {
    '>   "product": {
    '>     "id_product": 1,
    '>     "quantity": 1
    '>   }
    '> },
    '> {
    '>   "product": {
    '>     "id_product": 3,
    '>     "quantity": 4
    '>   }
    '> },
    '> {
    '>   "product": {
    '>     "id_product": 5,
    '>     "quantity": 2
    '>   }
    '> }]';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT JSON_VALID(@`example`);
 ------------------------ 
| JSON_VALID(@`example`) |
 ------------------------ 
|                      1 |
 ------------------------ 
1 row in set (0.00 sec)

mysql> SELECT JSON_LENGTH(@`example`);
 ------------------------- 
| JSON_LENGTH(@`example`) |
 ------------------------- 
|                       3 |
 ------------------------- 
1 row in set (0.00 sec)

mysql> SELECT
    ->   JSON_EXTRACT(@`example`, '$[0].product.id_product'),
    ->   JSON_EXTRACT(@`example`, '$[1].product.id_product'),
    ->   JSON_EXTRACT(@`example`, '$[2].product.id_product')G
*************************** 1. row ***************************
JSON_EXTRACT(@`example`, '$[0].product.id_product'): 1
JSON_EXTRACT(@`example`, '$[1].product.id_product'): 3
JSON_EXTRACT(@`example`, '$[2].product.id_product'): 5
1 row in set (0.00 sec)
 

Комментарии:

1. Отлично, я думаю, хотя использование mysql версии 5.7 (которую я использую), поддерживающей json, не работает должным образом, и лучший способ добиться этого — использовать, как и вы, 8.0.

2. @RamonB.C.: В MySQL 5.7 оба параметра работают без проблем, см. dbfiddle .