ORACLE json_object_t — ошибка при вызове метода get_string() для объекта, полученного цепочкой методов. get_array() .get()

#sql #oracle #plsql

Вопрос:

Я пытаюсь получить значение из массива, содержащегося в JSON-объекте, с помощью цепочки методов типа JSON_OBJECT_T — .get_array(…).get(0).get_string(…)

Но получаю исключение component 'GET_STRING' must be declared

Вот мой код, может кто-нибудь объяснить, почему цепь не работает?

 declare
    l_data clob := '{
        "data": {
            "foo": "bar",
            "persons": [{"code":100, "name":"Elon"}, {"code":200, "name":"Musk"}]
        }
    }';
    --
    function bool_to_char(val in boolean) return varchar2 is
    begin
        return case val when true then 'TRUE' else 'FALSE' end;
    end;
begin
    dbms_output.put_line(
        bool_to_char(
            json_object_t
                .parse(l_data)
                .get_object('data')
                .get_array('persons')
                .get(0)
                .is_object
        )
    );  -- TRUE - got object

    -- this code works - got "Elon"
    dbms_output.put_line(
        json_object_t
            .parse(
                json_object_t
                    .parse(l_data)
                    .get_object('data')
                    .get_array('persons')
                    .get(0)
                    .stringify
            )
            .get_string('name')
    );

    -- this code does not work - got exception "PLS-00302: component 'GET_STRING' must be declared"
    /*
    dbms_output.put_line(
        json_object_t
            .parse(l_data)
            .get_object('data')
            .get_array('persons')
            .get(0)
            .get_string('name')
    );
    */
end;
 

Ответ №1:

Проблема в том , что вызов .get(0) возвращает тип JSON_ELEMENT_T , а не JSON_OBJECT_T тип. JSON_ELEMENT_T не имеет GET_STRING метода, поэтому вы получаете сообщение об ошибке.

После использования get(0) вы можете TREAT использовать возвращаемое значение как a JSON_OBJECT_T , чтобы можно было вызвать GET_STRING метод.

Смотрите код ниже

 DECLARE
    l_data   CLOB := '{
        "data": {
            "foo": "bar",
            "persons": [{"code":100, "name":"Elon"}, {"code":200, "name":"Musk"}]
        }
    }';

    --
    FUNCTION bool_to_char (val IN BOOLEAN)
        RETURN VARCHAR2
    IS
    BEGIN
        RETURN CASE val WHEN TRUE THEN 'TRUE' ELSE 'FALSE' END;
    END;
BEGIN
    DBMS_OUTPUT.put_line (
        bool_to_char (
            json_object_t.parse (l_data).get_object ('data').get_array ('persons').get (0).is_object)); -- TRUE - got object

    -- this code works - got "Elon"
    DBMS_OUTPUT.put_line (
        json_object_t.parse (
            json_object_t.parse (l_data).get_object ('data').get_array ('persons').get (0).stringify).get_string (
            'name'));

    -- this code does not work - got exception "PLS-00302: component 'GET_STRING' must be declared"
    --Fixed using TREAT(... as JSON_OBJECT_T)
    DBMS_OUTPUT.put_line (
        TREAT (
            json_object_t.parse (l_data).get_object ('data').get_array ('persons').get (0)
                AS json_object_t).get_string ('name'));
END;