• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
JSON in-depth validation

#1
Hi,

I am looking for an elegant way to validate some json-encoded values coming form a post. I consider valid_json helper function merely a first stage validation, to let me throw away syntactically incorrect input. What I would like to do is validate all the values in a resulting array after json_decode just as if they were posted without json. For this I am trying to implement a custom helper function to further validate the input, but i can't seem to pass an array as an argument to it.  The array would need to hold further validation rules concordant with CI4 validation rule syntax, dot matrix syntax included. Has anyone got an idea other than adding secondary validation in the relevent controller's method?

Secondly, even if I pass an json-encoded argument only to decode into an array, how do you request a validator run from inside of a helper function not having access to class pointer?

For now I managed to come up with this:

PHP Code:
public $rule = [
 
'values' => [
  'rules' => 'trim|required|valid_json|json_contain_fields[id,name,owner_id]'
  ]


json_contain_fields being my helper function. It is now limited only to checking if certain keys exist in the array after json_decode.
Reply

#2
I seem to have come up with a solution. Here's the helper function:

PHP Code:
    public function json_valid_fields($arg = null, string $fields = null)
    {
        $data = json_decode($arg, $assoc = true, $depth = 15);
        if (json_last_error() !== JSON_ERROR_NONE)
        {
            log_message('error', 'json_valid_fields: invalid json string');
            return false;
        }

        $validator = Services::validation();

        // separate field names with rules
        foreach (explode(',', $fields) as $field)
        {
            $config = explode(':', $field);
            $key = $config[0];

            // separate rules for a field
            $rules = explode('|', $config[1]);
            if (isset($data[$key]))
            {
                // run the checks, break at first failure
                foreach ($rules as $rule)
                {
                    $result = $validator->check($data[$key], $rule);

                    if (! $result)
                        return false;
                }
            }
            elseif (in_array('required', $rules))
            {
                log_message('notice', 'json_valid_fields: key ' .$key. ' is required');
                return false;
            }
        }   

        return true
;
    

And this is how I feed it with validation rules:

PHP Code:
public $rule = [
    
'values' =>    [
        
'rules'    =>    'trim|required|json_valid_fields['
                
.'id:trim|required|is_natural_no_zero,'
                
.'parent_id:trim|is_natural_no_zero,'
                
.'name:trim|required|max_length[256],'
                
.'owner_id:trim|required|is_natural_no_zero,'
                
.']',
        
'errors'    =>    [
            
'json_valid_fields' => 'Invalid JSON data'
        
]
    ],
]; 

Each field+ruleset line is separated with ',', and field name is separated from ruleset with single ':'.
All this allows to validate both syntax and field values in one go.
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.