I'm trying to make a library that takes arbitrary data (well varchars, dates, numbers, collections and objects) and returns a Javascript Object Notation representation. I would like this to work something like:
lv_json_string := to_json(ANYDATA.CONVERTVARCHAR2('My data'));
I've got the basic types working, now I'm tackling objects. I can iterate over them and get their values but when the object contains a nested object it seems to be impossible to get at the object. Ideally I would be able to get an attribute back as ANYDATA regardless of type, at the moment I have a case statement that looks something like:
CASE p_type_code
WHEN DBMS_TYPES.TYPECODE_VARCHAR2 THEN
lv_error := p_data.getVarchar2(lv_varchar2);
RETURN ANYDATA.convertVarchar2(lv_varchar2);
WHEN DBMS_TYPES.TYPECODE_NUMBER THEN
lv_error := p_data.getNumber(lv_number);
RETURN ANYDATA.convertNumber(lv_number);
WHEN DBMS_TYPES.TYPECODE_OBJECT THEN
....
This is executed for each attribute and then I call to_json again recursively. When I have an object type, I cannot get at it. How do I:
a) Get at any attribute as an ANYDATA value? (this has to be a 'fresh' one so I can carry on iterating with the current one).
b) Get an arbitrary object out of an ANYDATA value and back in again?
A note on (b): I've tried using EXECUTE IMMEDIATE to set up a variable of the right type and do something similar to what I've got for the other types. The problem is that I always get an error about type mismatches. The same code hardcoded for a test type and run without execute immediate works fine, I think passing the current ANYDATA object into another block messes it's state up somehow. Here's that piece of code:
EXECUTE IMMEDIATE '
DECLARE
lv_data ANYDATA := :data;
lv_error BINARY_INTEGER;
lv_object ' || lv_type_name || ';
BEGIN
lv_error := lv_data.getObject(lv_object);
:result := ANYDATA.convertObject(lv_object);
END;' USING IN p_data, OUT lv_result;
Any ideas people?