How to use apex_json.get_count in a nested array

Viewed 611

I am trying to loop through the array from the count of the benefits element in my json. I keep getting numeric value error although get count function in apex json returns a number.

If we change the loop to for 1 in 1..2 - it works fine.

If we hardcode the array index to 1 then the code works but if we try to pass a variable using %d p0 then i get a numeric value error - ORA - 06502.

Below is the code:

  j              apex_json.t_values; 
  l_count_chg    number;
  l_count_pers   number;
  l_count_ben    number;
  
  l_members      wwv_flow_t_varchar2;
  l_paths        apex_t_varchar2;
  l_paths2       apex_t_varchar2;
  l_paths3       apex_t_varchar2; 

  v_get_person   varchar2(10); 
  v_get_benefit  varchar2(10);
  v_get_benopt   varchar2(10);
  r_count        number;
  
begin

  apex_json.parse(j,'{
    "PolicyUpdate": {
        "contractNumber": 12345,
        "effectiveDate": "2022-04-01",
        "planChanges": [
            {
                "changeCode": 1,
                "roleplayerId": "pers1",
                "person": {
                    "id": "pers1",
                    "surname": "Hazy",
                    "firstName": "Smith",
                    "benefits": [
                        {
                            "Id": "ben1",
                            "typeCode": "C1",
                            "benefitName": "Funeral Benefit",
                            "roleplayerId": "pers1",
                            "coverAmount": 10000,
                            "premiumAmount": 47.47,
                            "StartDate": "2021-04-01",
                            "Options": {
                                "Option": [
                                    {
                                        "Label": "Risk Benefit Classification",
                                        "Value": "Main Life"
                                    },
                                    {
                                        "Label": "Waiting Period (DOC to Event)",
                                        "Value": "6 Months"
                                    },
                                    {
                                        "Label": "Paid Up Benefit (Y/N)",
                                        "Value": "No"
                                    }
                                ]
                            }
                        },
                        {
                            "Id": "ben2",
                            "typeCode": "C1",
                            "benefitName": "Tombstone Benefit",
                            "roleplayerId": "pers1",
                            "coverAmount": 5000,
                            "premiumAmount": 10.47,
                            "StartDate": "2021-04-01"
                        }
                    ]
                }
            },
            {
                "changeCode": 2,
                "roleplayerId": "pers2"
            }
        ]
    }
}');

  dbms_output.put_line('Contract Number  : ' ||
                       apex_json.get_varchar2(p_path => 'PolicyUpdate.contractNumber'));
  dbms_output.put_line('Effective Adte   : ' ||
                       apex_json.get_varchar2(p_path => 'PolicyUpdate.effectiveDate'));
  dbms_output.put_line('----------------------------------------');
  
  
  l_count_chg := apex_json.get_count(p_path => 'PolicyUpdate.planChanges',p_values=>j);
  dbms_output.put_line('change count '||l_count_chg);
  
  for i in 1..l_count_chg loop   
    dbms_output.put_line('changeCode    '||apex_json.get_varchar2(p_path => 'PolicyUpdate.planChanges[%d].changeCode'  ,p_values=>j,p0     => i));
    dbms_output.put_line('roleplayerId  '||apex_json.get_varchar2(p_path => 'PolicyUpdate.planChanges[%d].roleplayerId',p_values=>j,p0     => i));   
    dbms_output.put_line('firstname     '||apex_json.get_varchar2(p_path => 'PolicyUpdate.planChanges[%d].person.firstName',p_values=>j,p0 => i));                                   
    
    l_count_ben := apex_json.get_count(p_path => 'PolicyUpdate.planChanges[%d].person.benefits',p_values=>j);   
    dbms_output.put_line('benefit count '|| l_count_ben);
    
    for x in 1..l_count_ben loop    
      dbms_output.put_line('ben id        '||apex_json.get_varchar2(p_path => 'PolicyUpdate.planChanges[%d].person.benefits[%d].Id',p_values=>j,p0 => i,p1 => x));       
    end loop;    
                     
  end loop; 
  
end;

2 Answers

For me the count didn't return a number (just no value) so I made some changes - I found it safest to check if the path exists before getting the count:

declare
  j              apex_json.t_values; 
  l_count_chg    number;
  l_count_pers   number;
  l_count_ben    number;
  
  l_members      wwv_flow_t_varchar2;
  l_paths        apex_t_varchar2;
  l_paths2       apex_t_varchar2;
  l_paths3       apex_t_varchar2; 

  v_get_person   varchar2(10); 
  v_get_benefit  varchar2(10);
  v_get_benopt   varchar2(10);
  r_count        number;
  
begin

  apex_json.parse(j,'{
    "PolicyUpdate": {
        "contractNumber": 12345,
        "effectiveDate": "2022-04-01",
        "planChanges": [
            {
                "changeCode": 1,
                "roleplayerId": "pers1",
                "person": {
                    "id": "pers1",
                    "surname": "Hazy",
                    "firstName": "Smith",
                    "benefits": [
                        {
                            "Id": "ben1",
                            "typeCode": "C1",
                            "benefitName": "Funeral Benefit",
                            "roleplayerId": "pers1",
                            "coverAmount": 10000,
                            "premiumAmount": 47.47,
                            "StartDate": "2021-04-01",
                            "Options": {
                                "Option": [
                                    {
                                        "Label": "Risk Benefit Classification",
                                        "Value": "Main Life"
                                    },
                                    {
                                        "Label": "Waiting Period (DOC to Event)",
                                        "Value": "6 Months"
                                    },
                                    {
                                        "Label": "Paid Up Benefit (Y/N)",
                                        "Value": "No"
                                    }
                                ]
                            }
                        },
                        {
                            "Id": "ben2",
                            "typeCode": "C1",
                            "benefitName": "Tombstone Benefit",
                            "roleplayerId": "pers1",
                            "coverAmount": 5000,
                            "premiumAmount": 10.47,
                            "StartDate": "2021-04-01"
                        }
                    ]
                }
            },
            {
                "changeCode": 2,
                "roleplayerId": "pers2"
            }
        ]
    }
}');

  dbms_output.put_line('Contract Number  : ' ||
                       apex_json.get_varchar2(p_path => 'PolicyUpdate.contractNumber',p_values => j));
  dbms_output.put_line('Effective Adte   : ' ||
                       apex_json.get_varchar2(p_path => 'PolicyUpdate.effectiveDate',p_values => j));
  dbms_output.put_line('----------------------------------------');
  
  
  l_count_chg := apex_json.get_count(p_path => 'PolicyUpdate.planChanges',p_values=>j);
  dbms_output.put_line('change count '||l_count_chg);
  
  for i in 1..l_count_chg loop   
    dbms_output.put_line('changeCode    '||apex_json.get_varchar2(p_path => 'PolicyUpdate.planChanges[%d].changeCode'  ,p_values=>j,p0     => i));
    dbms_output.put_line('roleplayerId  '||apex_json.get_varchar2(p_path => 'PolicyUpdate.planChanges[%d].roleplayerId',p_values=>j,p0     => i));   
    dbms_output.put_line('firstname     '||apex_json.get_varchar2(p_path => 'PolicyUpdate.planChanges[%d].person.firstName',p_values=>j,p0 => i));                                   


    IF apex_json.does_exist(p_path => 'PolicyUpdate.planChanges[%d].person.benefits',p0 => i,p_values=>j) THEN 
      l_count_ben := apex_json.get_count(p_path => 'PolicyUpdate.planChanges[%d].person.benefits',p0 => i,p_values=>j);   
      dbms_output.put_line('benefit count '|| l_count_ben);
      for x in 1..l_count_ben loop    
        dbms_output.put_line('ben id        '||apex_json.get_varchar2(p_path => 'PolicyUpdate.planChanges[%d].person.benefits[%d].Id',p_values=>j,p0 => i,p1 => x));       
      end loop;    
    END IF;                      
  end loop; 
end;

Koen's suggestion of testing with EXISTS is excellent.

He also added this, but didn't spell out that your original version seemed to be missing the parameter:

p0 => i

when calculating l_count_ben

So the get_count value would have been unknown.

Related