TransWikia.com

Как добавить пустую строку в JSON_OBJECT_T объект?

Stack Overflow на русском Asked on January 28, 2021

Пробую добавить пустую строку к сушности типа JSON_OBJECT_T, но как результат получаю значение null, а не пустую строку.

DECLARE
   V_OBJ JSON_OBJECT_T;
BEGIN
   V_OBJ := JSON_OBJECT_T();
   V_OBJ.PUT('customerAccRef','');
   DBMS_OUTPUT.PUT_LINE(V_OBJ.stringify);
END;

Результат работы кода выше, следующий JSON:

{"customerAccRef":null}

, но желаемый результат такой:

{"customerAccRef":""}

Может кто-то подсказать, что надо изменить, чтобы получить пустую строку?


Свободный перевод вопроса How to put empty string in JSON_OBJECT_T object? от участника @Kinjan Bhavsar

2 Answers

Для лучшей читаемости, предложил бы как решение квотированный литерал, как то так:

var jsonObject varchar2 (32)
declare 
    jo json_object_t := json_object_t();
begin 
    jo.put ('abc', q'""');
    :jsonObject := jo.stringify ();
end;
/

JSONOBJECT
----------
{"abc":""}

Две одиночные кавычки '' это символьный литерал и его значение - пустая строка, а не NULL. Расхождение со стандартом SQL начинается при присвоении символьного литерала переменной или колонке с конкретным типом данных.

Выше упомянут стандарт SQL, но PL/SQL это не SQL и поведение может отличаться. Например, обе переменные имеют значение NULL, но как параметры для встроенных функций БД они интерпретируются по разному:

var ret varchar2 (64)
declare 
    jo json_object_t := json_object_t();
    nullstr  varchar2(1) := null; 
    zerostr varchar2(1) := ''; 
begin 
    jo.put ('foo', nullstr);
    jo.put ('bar', zerostr);
    :ret := jo.stringify ()||' # >>'||nullstr||zerostr||'<< '|| 
        case when nullstr is null and zerostr is null then 'both values are null' end;
end;
/

RET
-------------------------------------------------
{"foo":null,"bar":""} # >><< both values are null

Это отличие в поведении пока не документированно. В SQL, напротив, литерал с пустой строкой при присвоении становится NULL, никаких отличий в поведении нет:

select 
    json_object ('foo' value q'""') jo1, 
    json_object ('bar' value trim (' ')) jo2, 
    json_object ('baz' value cast ('' as varchar2(1))) jo3 
from dual
/

JO1              JO2              JO3             
---------------- ---------------- ----------------
{"foo":null}     {"bar":null}     {"baz":null}    

Answered by 0xdb on January 28, 2021

Причина такого поведения, потому что Oracle иннерпретирует пустую строку как NULL.

Так исторически сложилось, что поведение пустой строки отличается от стандарта SQL, и можно почитать в этом ответе, чтобы ознакомиться с этим более подробно.
Прим.ред.: на SO по русски можно найти аналогичную информацию в этой теме, или в этой с укороченным переводом ответа выше.

Сам я не смог найти нигде в документации по JSON объектам, описания, как обойти эту проблему. Был бы рад, если бы кто-нибудь смог подсказать, где её можно найти.

В качестве пути решения, можно использовать функцию TRIM для преобразования одного пробела в пустую строку, вот так:

V_OBJ.PUT('customerAccRef' , TRIM(' '));

Что даст:

{"customerAccRef":""}

Похоже, это работает как в версии 12.2, тестировал на локальной машине, так и в 18c db<>fiddle, а также в 19c LiveSQL.

Здесь следует заметить, что запрос select TRIM(' ') from dual всегда возвращает NULL. Это удивительно, почему он работает как ожидалось с JSON объектами.

Свободный перевод ответа от участника @Kaushik Nayak

Answered by 0xdb on January 28, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP