Как заменить «-» только в * текстовом * значении любого универсального jsonb в postgresql?

#json #postgresql #postgresql-10

#json #postgresql #postgresql-10

Вопрос:

Мне нужно очистить данные JSON, которые могли бы выглядеть как:

 {
   "reference":"0000010-CAJ",
   "product_code":"00000-10",
   "var_name":"CAJ-1",
   "doc_date":"2020-02-09T21:01:01-05:00",
   "due_date":"2020-03-10T21:01:01-05:00",
}
  

Однако это всего лишь одна из многих других возможностей (для агрегации журналов, которая получает данные из многих источников).

Мне нужно заменить «-» на «_», но без разрыва дат, таких как «2020-03-10T21: 01: 01-05:00», поэтому я не могу просто преобразовать в строку и выполнить замену. Интересно, существует ли эквивалент:

 for (k,v) in json:
   if is_text(v):
       v = replace(...)
  

Ответ №1:

Вы можете проверить с помощью регулярного выражения, похоже ли значение на временную метку:

 update the_table 
  set the_column = (select 
                     jsonb_object_agg(
                         key, 
                         case 
                            when value ~ '^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.*' then value
                           else replace(value, '-', '_')
                         end)
                    from jsonb_each_text(the_column) as t(key, value))
  

Это перебирает все пары ключ / значение в столбце JSON (используя jsonb_each_text() ) и снова собирает их все обратно в JSON (используя jsonb_object_agg()). Значения, которые выглядят как временная метка, остаются неизменными, для всех остальных - заменяется на _ .

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

1. Это помогает фильтровать даты, но не выбирать только текстовые значения…

2. @mamcx: извините, тогда я не знаю, чего именно вы хотите.