1

I have to create a function that takes an object of this type :

    "users":"John",
    "Level":"1",
    "list":[
      {"id":"1", "price1":"100.50", "price2":"90.50"},
      {"id":"2", "price1":"100.60", "price2":"80.50"},
      {"id":"2", "price1":"105.50", "price2":"700.50"}
    ]}

For information JSON is not obliged but it is the thing that seemed the simplest to me. But maybe the creation of a POSTGRES type can work.

Then how to process the object if I use a JSON or PostGres Type.

    CREATE OR REPLACE FUNCTION MYFUNCTION(myobject JSON ? CREATE TYPE ? )
      RETURNS TABLE (
        "OK" BOOLEAN,
        "NB" VARCHAR
      )
    
    AS $$
    
    DECLARE
    
    
    BEGIN
    
    -- I would like to get for each object in the list the price1 and price2 to 
       compare them. 
    
    END; $$
    
    LANGUAGE 'plpgsql';
Enlico
  • 23,259
  • 6
  • 48
  • 102
MyJobIsHard
  • 25
  • 1
  • 6
  • It is absolutely not clear what you are trying to achieve. What is your expected result? – S-Man Jan 13 '21 at 09:06
  • i want to recup all object in the list and compare price1 and price2, but how can recup for each object in the "list" ? – MyJobIsHard Jan 13 '21 at 09:13

2 Answers2

1

The crux of the question seems to be how to extract the values from the json object. This is one way:

select * from json_to_recordset('{
     "users":"John",
     "Level":"1",
     "list":[
      {"id":"1", "price1":"100.50", "price2":"90.50"},
      {"id":"2", "price1":"100.60", "price2":"80.50"},
      {"id":"2", "price1":"105.50", "price2":"700.50"}
    ]}'::json->'list') as foo(id int, price1 numeric, price2 numeric);

With a json variable instead of the literal string:

select * from json_to_recordset(jsonvariable->'list') as foo(id int, price1 numeric, price2 numeric)

Note. The json object you provide isn't legal. Some commas missing. I'd also suggest you use jsonb instead of json.

Edited:This is a skeleton on how you can use this in a plpgsql function:

create or replace function func(jsonvariable json) returns table (ok boolean, nb text) as 
$BODY$
declare 
    r record;
begin
    for r in (select * from json_to_recordset(jsonvariable->'list') as foo(id int, price1 numeric, price2 numeric)) loop
        --- DO THINGS
        ok:=(r.price1>r.price2);
        nb:='this is text returned';
        return next;
    end loop;
end;
$BODY$
language plpgsql;
Enlico
  • 23,259
  • 6
  • 48
  • 102
Bjarni Ragnarsson
  • 1,731
  • 1
  • 6
  • 8
1

No Need to use loop for processing on the JSON ARRAY. you can use JSONB_ARRAY_ELEMENTS or JSONB_TO_RECORDSET for your requirement like below:

Using JSONB_TO_RECORDSET

CREATE OR REPLACE FUNCTION MYFUNCTION(myobject JSONB)
      RETURNS TABLE (ok BOOLEAN, nb VARCHAR)
      AS 
      $$
      BEGIN
       return query
        select 
           price1>price2,     -- you can change the condition here
           id::varchar        -- you can change the value as per your requirement
        from jsonb_to_recordset(myobject ->'list') as x(id int, price1 numeric, price2 numeric);
    
    END; 
$$
    
LANGUAGE 'plpgsql';

Using JSONB_ARRAY_ELEMENTS

CREATE OR REPLACE FUNCTION MYFUNCTION1(myobject JSONB)
      RETURNS TABLE (ok BOOLEAN, nb VARCHAR)
      AS 
      $$
      BEGIN
       return query
        select 
           (x->>'price1')::numeric > (x->>'price2')::numeric,     -- you can change the condition here
           (x->>'id')::varchar                                    -- you can change the value as per your requirement
        from jsonb_array_elements(myobject ->'list') as x;
    
    END; 
$$
    
LANGUAGE 'plpgsql';

DEMO

Akhilesh Mishra
  • 5,876
  • 3
  • 16
  • 32