opis / json-schema

JSON Schema validator for PHP
https://opis.io/json-schema
Apache License 2.0
568 stars 58 forks source link

[Question] How to use default values after validation? #121

Open jsaak opened 2 years ago

jsaak commented 2 years ago

Given the schema:

    "type" => "string",
    "enum" => ["en","hu","de","sk"],
    "default" => "en",

I want to use the string value in my code after the validation. However i could not find a way to get it, when the user does not send this parameter at all.

How do I do that?

killua-eu commented 9 months ago

@jsaak , did you figure out? I'm having the same problem

jsaak commented 9 months ago

No, I gave up on this repo. I wrote a validator myself, here it is if you want, works for me:

<?php
  if (PHP_SAPI === 'cli') {
    //$def = [ "type" => "array", "items" => ["type" => "integer" ]];
    //$input = [ 1 , 2 , "asds" ];

    //$def = [ "type" => "array", 
             //"items" => ["type" => "object", 
                         //"properties" => ["age" => [ "type" => "number"]],
                         //"additionalProperties" => false,
                         //"required" => ['age'],
                        //]
                   //];

    //$def = [ "type" => "array", 
             //"items" => ["type" => "object", 
                         //"properties" => ["age" => [ "type" => "number"]],
                        //]
                   //];
    //$input = [ ["age" => 1], ["age" => 3], ["name" => "n"]];

    $def = ["anyOf" => [
      ["type" => "object", "properties" => ["age" => [ "type" => "number"]]], 
      ["type" => "null"],
    ]];
    $input = ["asdf" => "adf"];

    set_strict($def);

    $r = validate($def, $input, 'root');
    echo json_encode($r);
  }

  function set_strict(&$def) {
    if (array_key_exists('anyOf',$def)) {
      foreach($def["anyOf"] as &$item) {
        set_strict($item);
      }
    } elseif (array_key_exists('type',$def)) {
      if ($def['type'] === "array") {
        set_strict($def['items']);
      } elseif($def['type'] === "object") {
        $def['additionalProperties'] = false;
        $def['required'] = array_keys($def['properties']);
        foreach($def["properties"] as $prop_n=> &$prop) {
          set_strict($prop);
        }
      }
    }
  }

  function validate($def,&$input,$descriptor = '',$prop_name = null) {
    global $qSql; //TODO remove global, use function parameter instead?
    //echo "validating: " . json_encode($def) . "\n";

    if (array_key_exists('anyOf',$def)) {
      $errors = [];
      foreach($def['anyOf'] as $item) {
        $r = validate($item, $input, $descriptor . '.anyOf');
        if ($r === '') {
          return "";
        } else {
          array_push($errors,$r);
        }
      }
      return "$descriptor anyOf errors: *** ".implode($errors, " *** ");
    } elseif (array_key_exists('type',$def)) {
      if ($def['type'] === "integer") {
        if (!((is_int($input) || $input === 0.0 ))) { return "$descriptor is not an integer"; }
      } elseif ($def['type'] === "number") {
        if (!(is_int($input) || is_float($input))) { return "$descriptor is not a number"; }
      } elseif ($def['type'] === "boolean") {
        if (!is_bool($input))    { return "$descriptor is not a boolean"; }
      } elseif ($def['type'] === "null") {
        if (!is_null($input))    { return "$descriptor is not null"; }
      } elseif ($def['type'] === "string") {
        if (!is_string($input))  { return "$descriptor is not a string"; }

        //format
        if (array_key_exists('format',$def)) {
          if ($def['format'] === "date") {
            if (preg_match("/^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/",$input) !== 1) {
              return "$descriptor is not a valid date, see RFC3339 section-5.6";
            }
          } elseif ($def['format'] === "time") {
            if (preg_match("/^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))$/",$input) !== 1) {
              return "$descriptor is not a valid time, see RFC3339 section-5.6";
            }
          } elseif ($def['format'] === "date-time") {
            if (preg_match("/^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt ]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))$/",$input) !== 1) {
              return "$descriptor is not a valid date-time, see RFC3339 section-5.6";
            }
          } elseif ($def['format'] === "money") {
            if (preg_match("^[0-9]+\.?[0-9]*$",$input) !== 1) {
              return "$descriptor is not a money amount, must be a string containing only numbers and optionally a .";
            }
          } else {
            return "$descriptor unsupported format: ".$def['format'];
          }
        }

        //pattern
        if (array_key_exists('pattern',$def)) {
          if (1 !== preg_match('/'.$def['pattern'].'/',$input)) {
            return "$descriptor is not valid, pattern /".$def['pattern'] . "/";
          }
        }

        //enum
        if (array_key_exists('enum',$def)) {
          if (!in_array($input,$def['enum'])) {
            return "$descriptor invlaid value, use these: ". implode(',',$def['enum']);
          }
        }

        //escape string
        $input = mysqli_real_escape_string($qSql, $input);
      } elseif ($def['type'] === "array") {
        if (!is_array($input))   { return "$descriptor is not an array"; }
        if ((count($input) > 0) && (!array_key_exists(0,$input)))   { return "$descriptor is not an array"; }
        foreach($input as $index => $item) { //iterate on input
          $r = validate($def['items'], $item, $descriptor . "[$index]", null);
          if ($r !== '') { return $r; }
        }
      } elseif($def['type'] === "object") {
        if (!is_array($input))   { return "$descriptor is not an object"; }
        if ((count($input) > 0) && (array_key_exists(0,$input)))   { return "$descriptor is not an object"; }

        // required
        if (array_key_exists("required",$def)) {
          foreach($def["required"] as $p) {
            if (!array_key_exists($p,$input)) {
              return "$descriptor missing parameter: $p";
            }
          }
        }

        // additionalProperties
        if (array_key_exists("additionalProperties",$def)) {
          if ($def["additionalProperties"] == false) {
            $ad = array_diff_key($input,$def['properties']);
            if (count($ad) > 0) {
              return "$descriptor unexpected additional property: ".join(array_keys($ad));
            }
          }
        }

        foreach($def["properties"] as $prop_n=> $prop) {
          // prop missing
          if (!array_key_exists($prop_n,$input)) {
            if (array_key_exists('default',$prop)) {
              $input[$prop_n] = $prop['default'];
            } else {
              $input[$prop_n] = null;
            }
            // prop found
          } else {
            $r = validate($prop, $input[$prop_n], $descriptor . ".$prop_n", $prop_n );
            if ($r !== '') { return $r; }
          }
        }
      } else {
        return "$descriptor unknown data type: ".$def['type'];
      }
      return ''; // when returning anything else than '' then we quit the recursion
    } else {
      return "$descriptor invalid definition ?!?" . json_encode($def);
    }
  }
?>