<?php
function validateJsonSchema($json, $schema, $checkRequired=true)
{
$decodeIfNeeded=function ($maybeJson) {
if (is_string($maybeJson)) {
try {
return json_decode($maybeJson, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return false;
}
} else {
return $maybeJson;
}
};
$json = $decodeIfNeeded($json);
$schema = $decodeIfNeeded($schema);
if (!$json||!$schema) {
return "failed to decode json";
}
if (is_string($schema)) {
try {
$schema=json_decode($schema, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return "schema cannot be decoded";
}
}
if ($checkRequired) {
$missingRequiredKeys=[];
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "required")
&&$schemaValue->required) {
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach ($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if ($type=="object") {//Needed to handle array situations
foreach ($schema as $schemaKey => $schemaValue) {
if (!property_exists($schemaValue, "type")
||!is_string($schemaValue->type)) {
$res=validateJsonSchema($jsonValue, $schemaValue, $checkRequired);
if ($res!="") {
return $res;
}
}
}
} else {
$schemaProperties=null;
if (!is_array($schema)) {
if ($checkRequired) {
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if ($missingKey!== false) {
unset($missingRequiredKeys[$missingKey]);
}
}
if (!is_array($schema)&&!property_exists($schema, $jsonKey)) {
return "key not in schema";
}
$schemaProperties=$schema->$jsonKey;
} else {
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "type")
&&is_string($schemaValue->type)) {//This is a single value within an array
if ($type==$schemaValue->type) {
$schemaProperties=$schemaValue;
break;
}
}
}
}
if (!(is_null($jsonValue)&&property_exists($schemaProperties, "nullable")&&$schemaProperties->nullable)) {
if (is_null($schemaProperties)) {
return "type not allowed: ".$type;
}
if ($schemaProperties->type!=$type) {
if (!($type=="integer"&&$schemaProperties->type=="double")) {//integer instead of double is acceptable
return "type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey;
}
}
$getSchemaProperty=function ($schemaProperties, $name) {
if (property_exists($schemaProperties, $name)) {
return $schemaProperties->$name;
}
if ($name=="min") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MIN;
}
return PHP_INT_MIN;
}
if ($name=="max") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MAX;
}
return PHP_INT_MAX;
}
return null;
};
switch ($schemaProperties->type) {
case "string":
$count=strlen($jsonValue);
break;
case "integer":
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue, $getSchemaProperty($schemaProperties, "data"), $checkRequired);
if ($res!="") {
return $res;
}
$count=count($jsonValue);
break;
default:
return "unknown type ".$schemaProperties->type;
break;
}
$min=$getSchemaProperty($schemaProperties, "min");
$max=$getSchemaProperty($schemaProperties, "max");
if ($count<$min) {
return "too short";
}
if ($count>$max) {
return "too long";
}
}
}
}
if ($checkRequired&&count($missingRequiredKeys)>0) {
return "missing required key(s)";
}
return "";
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json, $schema)."\n");
?>
<?php
function validateJsonSchema($json, $schema, $checkRequired=true)
{
$decodeIfNeeded=function ($maybeJson) {
if (is_string($maybeJson)) {
try {
return json_decode($maybeJson, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return false;
}
} else {
return $maybeJson;
}
};
$json = $decodeIfNeeded($json);
$schema = $decodeIfNeeded($schema);
if (!$json||!$schema) {
return "failed to decode json";
}
if (is_string($schema)) {
try {
$schema=json_decode($schema, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return "schema cannot be decoded";
}
}
if ($checkRequired) {
$missingRequiredKeys=[];
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "required")
&&$schemaValue->required) {
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach ($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if ($type=="object") {//Needed to handle array situations
foreach ($schema as $schemaKey => $schemaValue) {
if (!property_exists($schemaValue, "type")
||!is_string($schemaValue->type)) {
$res=validateJsonSchema($jsonValue, $schemaValue, $checkRequired);
if ($res!="") {
return $res;
}
}
}
} else {
$schemaProperties=null;
if (!is_array($schema)) {
if ($checkRequired) {
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if ($missingKey!== false) {
unset($missingRequiredKeys[$missingKey]);
}
}
if (!is_array($schema)&&!property_exists($schema, $jsonKey)) {
return "key not in schema";
}
$schemaProperties=$schema->$jsonKey;
} else {
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "type")
&&is_string($schemaValue->type)) {//This is a single value within an array
if ($type==$schemaValue->type) {
$schemaProperties=$schemaValue;
break;
}
}
}
}
if (!(is_null($jsonValue)&&property_exists($schemaProperties, "nullable")&&$schemaProperties->nullable)) {
if (is_null($schemaProperties)) {
return "type not allowed: ".$type;
}
if ($schemaProperties->type!=$type) {
if (!($type=="integer"&&$schemaProperties->type=="double")) {//integer instead of double is acceptable
return "type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey;
}
}
$getSchemaProperty=function ($schemaProperties, $name) {
if (property_exists($schemaProperties, $name)) {
return $schemaProperties->$name;
}
if ($name=="min") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MIN;
}
return PHP_INT_MIN;
}
if ($name=="max") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MAX;
}
return PHP_INT_MAX;
}
return null;
};
switch ($schemaProperties->type) {
case "string":
$count=strlen($jsonValue);
break;
case "integer":
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue, $getSchemaProperty($schemaProperties, "data"), $checkRequired);
if ($res!="") {
return $res;
}
$count=count($jsonValue);
break;
default:
return "unknown type ".$schemaProperties->type;
break;
}
$min=$getSchemaProperty($schemaProperties, "min");
$max=$getSchemaProperty($schemaProperties, "max");
if ($count<$min) {
return "too short";
}
if ($count>$max) {
return "too long";
}
}
}
}
if ($checkRequired&&count($missingRequiredKeys)>0) {
return "missing required key(s)";
}
return "";
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json, $schema)."\n");
?>
<?php
function validateJsonSchema($json, $schema, $checkRequired=true)
{
$decodeIfNeeded=function ($maybeJson) {
if (is_string($maybeJson)) {
try {
return json_decode($maybeJson, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return false;
}
} else {
return $maybeJson;
}
};
$json = $decodeIfNeeded($json);
$schema = $decodeIfNeeded($schema);
if (!$json||!$schema) {
return "failed to decode json";
}
if ($checkRequired) {
$missingRequiredKeys=[];
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "required")
&&$schemaValue->required) {
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach ($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if ($type=="object") {//Needed to handle array situations
foreach ($schema as $schemaKey => $schemaValue) {
if (!property_exists($schemaValue, "type")
||!is_string($schemaValue->type)) {
$res=validateJsonSchema($jsonValue, $schemaValue, $checkRequired);
if ($res!="") {
return $res;
}
}
}
} else {
$schemaProperties=null;
if (!is_array($schema)) {
if ($checkRequired) {
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if ($missingKey!== false) {
unset($missingRequiredKeys[$missingKey]);
}
}
if (!is_array($schema)&&!property_exists($schema, $jsonKey)) {
return "key not in schema";
}
$schemaProperties=$schema->$jsonKey;
} else {
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "type")
&&is_string($schemaValue->type)) {//This is a single value within an array
if ($type==$schemaValue->type) {
$schemaProperties=$schemaValue;
break;
}
}
}
}
if (!(is_null($jsonValue)&&property_exists($schemaProperties, "nullable")&&$schemaProperties->nullable)) {
if (is_null($schemaProperties)) {
return "type not allowed: ".$type;
}
if ($schemaProperties->type!=$type) {
if (!($type=="integer"&&$schemaProperties->type=="double")) {//integer instead of double is acceptable
return "type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey;
}
}
$getSchemaProperty=function ($schemaProperties, $name) {
if (property_exists($schemaProperties, $name)) {
return $schemaProperties->$name;
}
if ($name=="min") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MIN;
}
return PHP_INT_MIN;
}
if ($name=="max") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MAX;
}
return PHP_INT_MAX;
}
return null;
};
switch ($schemaProperties->type) {
case "string":
$count=strlen($jsonValue);
break;
case "integer":
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue, $getSchemaProperty($schemaProperties, "data"), $checkRequired);
if ($res!="") {
return $res;
}
$count=count($jsonValue);
break;
default:
return "unknown type ".$schemaProperties->type;
break;
}
$min=$getSchemaProperty($schemaProperties, "min");
$max=$getSchemaProperty($schemaProperties, "max");
if ($count<$min) {
return "too short";
}
if ($count>$max) {
return "too long";
}
}
}
}
if ($checkRequired&&count($missingRequiredKeys)>0) {
return "missing required key(s)";
}
return "";
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json, $schema)."\n");
?>
<?php
function validateJsonSchema($json, $schema, $checkRequired=true)
{
$decodeIfNeeded=function ($maybeJson) {
if (is_string($maybeJson)) {
try {
return json_decode($maybeJson, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return false;
}
} else {
return $maybeJson;
}
};
$json = $decodeIfNeeded($json);
$schema = $decodeIfNeeded($schema);
if (!$json||!$schema) {
return( "failed to decode json");json";
}
if (is_string($schema)) {
try {
$schema=json_decode($schema, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return "schema cannot be decoded";
}
}
if ($checkRequired) {
$missingRequiredKeys=[];
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "required")
&&$schemaValue->required) {
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach ($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if ($type=="object") {//Needed to handle array situations
foreach ($schema as $schemaKey => $schemaValue) {
if (!property_exists($schemaValue, "type")
||!is_string($schemaValue->type)) {
$res=validateJsonSchema($jsonValue, $schemaValue, $checkRequired);
if ($res!="") {
return $res;
}
}
}
} else {
$schemaProperties=null;
if (!is_array($schema)) {
if ($checkRequired) {
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if ($missingKey!== false) {
unset($missingRequiredKeys[$missingKey]);
}
}
if (!is_array($schema)&&!property_exists($schema, $jsonKey)) {
return "key not in schema";
}
$schemaProperties=$schema->$jsonKey;
} else {
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "type")
&&is_string($schemaValue->type)) {//This is a single value within an array
if ($type==$schemaValue->type) {
$schemaProperties=$schemaValue;
break;
}
}
}
}
if (!(is_null($jsonValue)&&property_exists($schemaProperties, "nullable")&&$schemaProperties->nullable)) {
if (is_null($schemaProperties)) {
return "type not allowed: ".$type;
}
if ($schemaProperties->type!=$type) {
if (!($type=="integer"&&$schemaProperties->type=="double")) {//integer instead of double is acceptable
return "type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey;
}
}
$getSchemaProperty=function ($schemaProperties, $name) {
if (property_exists($schemaProperties, $name)) {
return $schemaProperties->$name;
}
if ($name=="min") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MIN;
}
return PHP_INT_MIN;
}
if ($name=="max") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MAX;
}
return PHP_INT_MAX;
}
return null;
};
switch ($schemaProperties->type) {
case "string":
$count=strlen($jsonValue);
break;
case "integer":
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue, $getSchemaProperty($schemaProperties, "data"), $checkRequired);
if ($res!="") {
return $res;
}
$count=count($jsonValue);
break;
default:
return "unknown type ".$schemaProperties->type;
break;
}
$min=$getSchemaProperty($schemaProperties, "min");
$max=$getSchemaProperty($schemaProperties, "max");
if ($count<$min) {
return "too short";
}
if ($count>$max) {
return "too long";
}
}
}
}
if ($checkRequired&&count($missingRequiredKeys)>0) {
return "missing required key(s)";
}
return "";
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json, $schema)."\n");
?>
<?php
function validateJsonSchema($json, $schema, $checkRequired=true)
{
$decodeIfNeeded=function ($maybeJson) {
if (is_string($maybeJson)) {
try {
return json_decode($maybeJson, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return false;
}
} else {
return $maybeJson;
}
};
$json = $decodeIfNeeded($json);
$schema = $decodeIfNeeded($schema);
if (!$json||!$schema) {
return("failed to decode json");
}
if (is_string($schema)) {
try {
$schema=json_decode($schema, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return "schema cannot be decoded";
}
}
if ($checkRequired) {
$missingRequiredKeys=[];
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "required")
&&$schemaValue->required) {
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach ($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if ($type=="object") {//Needed to handle array situations
foreach ($schema as $schemaKey => $schemaValue) {
if (!property_exists($schemaValue, "type")
||!is_string($schemaValue->type)) {
$res=validateJsonSchema($jsonValue, $schemaValue, $checkRequired);
if ($res!="") {
return $res;
}
}
}
} else {
$schemaProperties=null;
if (!is_array($schema)) {
if ($checkRequired) {
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if ($missingKey!== false) {
unset($missingRequiredKeys[$missingKey]);
}
}
if (!is_array($schema)&&!property_exists($schema, $jsonKey)) {
return "key not in schema";
}
$schemaProperties=$schema->$jsonKey;
} else {
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "type")
&&is_string($schemaValue->type)) {//This is a single value within an array
if ($type==$schemaValue->type) {
$schemaProperties=$schemaValue;
break;
}
}
}
}
if (!(is_null($jsonValue)&&property_exists($schemaProperties, "nullable")&&$schemaProperties->nullable)) {
if (is_null($schemaProperties)) {
return "type not allowed: ".$type;
}
if ($schemaProperties->type!=$type) {
if (!($type=="integer"&&$schemaProperties->type=="double")) {//integer instead of double is acceptable
return "type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey;
}
}
$getSchemaProperty=function ($schemaProperties, $name) {
if (property_exists($schemaProperties, $name)) {
return $schemaProperties->$name;
}
if ($name=="min") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MIN;
}
return PHP_INT_MIN;
}
if ($name=="max") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MAX;
}
return PHP_INT_MAX;
}
return null;
};
switch ($schemaProperties->type) {
case "string":
$count=strlen($jsonValue);
break;
case "integer":
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue, $getSchemaProperty($schemaProperties, "data"), $checkRequired);
if ($res!="") {
return $res;
}
$count=count($jsonValue);
break;
default:
return "unknown type ".$schemaProperties->type;
break;
}
$min=$getSchemaProperty($schemaProperties, "min");
$max=$getSchemaProperty($schemaProperties, "max");
if ($count<$min) {
return "too short";
}
if ($count>$max) {
return "too long";
}
}
}
}
if ($checkRequired&&count($missingRequiredKeys)>0) {
return "missing required key(s)";
}
return "";
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json, $schema)."\n");
?>
<?php
function validateJsonSchema($json, $schema, $checkRequired=true)
{
$decodeIfNeeded=function ($maybeJson) {
if (is_string($maybeJson)) {
try {
return json_decode($maybeJson, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return false;
}
} else {
return $maybeJson;
}
};
$json = $decodeIfNeeded($json);
$schema = $decodeIfNeeded($schema);
if (!$json||!$schema) {
return "failed to decode json";
}
if (is_string($schema)) {
try {
$schema=json_decode($schema, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return "schema cannot be decoded";
}
}
if ($checkRequired) {
$missingRequiredKeys=[];
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "required")
&&$schemaValue->required) {
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach ($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if ($type=="object") {//Needed to handle array situations
foreach ($schema as $schemaKey => $schemaValue) {
if (!property_exists($schemaValue, "type")
||!is_string($schemaValue->type)) {
$res=validateJsonSchema($jsonValue, $schemaValue, $checkRequired);
if ($res!="") {
return $res;
}
}
}
} else {
$schemaProperties=null;
if (!is_array($schema)) {
if ($checkRequired) {
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if ($missingKey!== false) {
unset($missingRequiredKeys[$missingKey]);
}
}
if (!is_array($schema)&&!property_exists($schema, $jsonKey)) {
return "key not in schema";
}
$schemaProperties=$schema->$jsonKey;
} else {
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "type")
&&is_string($schemaValue->type)) {//This is a single value within an array
if ($type==$schemaValue->type) {
$schemaProperties=$schemaValue;
break;
}
}
}
}
if (!(is_null($jsonValue)&&property_exists($schemaProperties, "nullable")&&$schemaProperties->nullable)) {
if (is_null($schemaProperties)) {
return "type not allowed: ".$type;
}
if ($schemaProperties->type!=$type) {
if (!($type=="integer"&&$schemaProperties->type=="double")) {//integer instead of double is acceptable
return "type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey;
}
}
$getSchemaProperty=function ($schemaProperties, $name) {
if (property_exists($schemaProperties, $name)) {
return $schemaProperties->$name;
}
if ($name=="min") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MIN;
}
return PHP_INT_MIN;
}
if ($name=="max") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MAX;
}
return PHP_INT_MAX;
}
return null;
};
switch ($schemaProperties->type) {
case "string":
$count=strlen($jsonValue);
break;
case "integer":
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue, $getSchemaProperty($schemaProperties, "data"), $checkRequired);
if ($res!="") {
return $res;
}
$count=count($jsonValue);
break;
default:
return "unknown type ".$schemaProperties->type;
break;
}
$min=$getSchemaProperty($schemaProperties, "min");
$max=$getSchemaProperty($schemaProperties, "max");
if ($count<$min) {
return "too short";
}
if ($count>$max) {
return "too long";
}
}
}
}
if ($checkRequired&&count($missingRequiredKeys)>0) {
return "missing required key(s)";
}
return "";
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json, $schema)."\n");
?>
<?php
function validateJsonSchema($json, $schema, $checkRequired=true)
{
$decodeIfNeeded=function ($maybeJson) {
if (is_string($json$maybeJson)) {
try {
$json=json_decode return json_decode($json$maybeJson, false, 512, JSON_THROW_ON_ERROR);
}
} catch (Exception $e) {
return("json cannotfalse;
be decoded"); }
} else {
return $maybeJson;
}
};
$json = $decodeIfNeeded($json);
$schema = $decodeIfNeeded($schema);
if (!$json||!$schema) {
return("failed to decode json");
}
if (is_string($schema)) {
try {
$schema=json_decode($schema, false, 512, JSON_THROW_ON_ERROR);
}
catch (Exception $e) {
return( "schema cannot be decoded");decoded";
}
}
if ($checkRequired) {
$missingRequiredKeys=[];
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "required")
&&$schemaValue->{"required"}>required) {
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach ($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if ($type=="object") {//Needed to handle array situations
foreach ($schema as $schemaKey => $schemaValue) {
if (!property_exists($schemaValue, "type")
||!is_string($schemaValue->type)) {
$res=validateJsonSchema($jsonValue, $schemaValue, $checkRequired);
if ($res!="") {
return($res); $res;
}
}
}
}
else {
$schemaProperties=null;
if (!is_array($schema)) {
if ($checkRequired) {
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if ($missingKey!== FALSEfalse) {
unset($missingRequiredKeys[$missingKey]);
}
}
if (!is_array($schema)&&!property_exists($schema, $jsonKey)) {
return( "key not in schema");schema";
}
$schemaProperties=$schema->$jsonKey;
}
else {
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "type")
&&is_string($schemaValue->type)) {//This is a single value within an array
if ($type==$schemaValue->type) {
$schemaProperties=$schemaValue;
break;
}
}
}
}
if (!(is_null($jsonValue)&&property_exists($schemaProperties, "nullable")&&$schemaProperties->nullable)) {
if (is_null($schemaProperties)) {
return( "type not allowed: ".$type);$type;
}
if ($schemaProperties->type!=$type) {
if (!($type=="integer"&&$schemaProperties->type=="double")) {//integer instead of double is acceptable
return( "type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey);$jsonKey;
}
}
$getSchemaProperty=function ($schemaProperties, $name) {
if (property_exists($schemaProperties, $name)) {
return( $schemaProperties->$name);>$name;
}
if ($name=="min") {
if ($schemaProperties->type=="double") {
return(PHP_FLOAT_MIN); PHP_FLOAT_MIN;
}
return(PHP_INT_MIN); PHP_INT_MIN;
}
if ($name=="max") {
if ($schemaProperties->type=="double") {
return(PHP_FLOAT_MAX); PHP_FLOAT_MAX;
}
return(PHP_INT_MAX); PHP_INT_MAX;
}
return(null); null;
};
switch ($schemaProperties->type) {
case "string":
$count=strlen($jsonValue);
break;
case "integer":
$count=$jsonValue;
break;
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue, $getSchemaProperty($schemaProperties, "data"), $checkRequired);
if ($res!="") {
return($res); $res;
}
$count=count($jsonValue);
break;
default:
return( "unknown type ".$schemaProperties->type);>type;
break;
}
$min=$getSchemaProperty($schemaProperties, "min");
$max=$getSchemaProperty($schemaProperties, "max");
if ($count<$min) {
return( "too short");short";
}
if ($count>$max) {
return( "too long");long";
}
}
}
}
if ($checkRequired&&count($missingRequiredKeys)>0) {
return( "missing required key(s)");";
}
return(""); "";
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json, $schema)."\n");
?>
<?php
function validateJsonSchema($json,$schema,$checkRequired=true){
if(is_string($json)){
try{
$json=json_decode($json,false,512,JSON_THROW_ON_ERROR);
}
catch(Exception $e){
return("json cannot be decoded");
}
}
if(is_string($schema)){
try{
$schema=json_decode($schema,false,512,JSON_THROW_ON_ERROR);
}
catch(Exception $e){
return("schema cannot be decoded");
}
}
if($checkRequired){
$missingRequiredKeys=[];
foreach($schema as $schemaKey => $schemaValue) {
if(property_exists($schemaValue,"required")
&&$schemaValue->{"required"}){
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if($type=="object"){//Needed to handle array situations
foreach($schema as $schemaKey => $schemaValue) {
if(!property_exists($schemaValue,"type")
||!is_string($schemaValue->type)){
$res=validateJsonSchema($jsonValue,$schemaValue,$checkRequired);
if($res!=""){
return($res);
}
}
}
}
else{
$schemaProperties=null;
if(!is_array($schema)){
if($checkRequired){
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if($missingKey!== FALSE){
unset($missingRequiredKeys[$missingKey]);
}
}
if(!is_array($schema)&&!property_exists($schema,$jsonKey)){
return("key not in schema");
}
$schemaProperties=$schema->$jsonKey;
}
else{
foreach($schema as $schemaKey => $schemaValue) {
if(property_exists($schemaValue,"type")
&&is_string($schemaValue->type)){//This is a single value within an array
if($type==$schemaValue->type){
$schemaProperties=$schemaValue;
break;
}
}
}
}
if(!(is_null($jsonValue)&&property_exists($schemaProperties,"nullable")&&$schemaProperties->nullable)){
if(is_null($schemaProperties)){
return("type not allowed: ".$type);
}
if($schemaProperties->type!=$type){
if(!($type=="integer"&&$schemaProperties->type=="double")){//integer instead of double is acceptable
return("type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey);
}
}
$getSchemaProperty=function($schemaProperties,$name){
if(property_exists($schemaProperties,$name)){
return($schemaProperties->$name);
}
if($name=="min"){
if($schemaProperties->type=="double"){
return(PHP_FLOAT_MIN);
}
return(PHP_INT_MIN);
}
if($name=="max"){
if($schemaProperties->type=="double"){
return(PHP_FLOAT_MAX);
}
return(PHP_INT_MAX);
}
return(null);
};
switch($schemaProperties->type){
case "string":
$count=strlen($jsonValue);
break;
case "integer":
$count=$jsonValue;
break;
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue,$getSchemaProperty($schemaProperties,"data"),$checkRequired);
if($res!=""){
return($res);
}
$count=count($jsonValue);
break;
default:
return("unknown type ".$schemaProperties->type);
break;
}
$min=$getSchemaProperty($schemaProperties,"min");
$max=$getSchemaProperty($schemaProperties,"max");
if($count<$min){
return("too short");
}
if($count>$max){
return("too long");
}
}
}
}
if($checkRequired&&count($missingRequiredKeys)>0){
return("missing required key(s)");
}
return("");
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json,$schema)."\n");
?>
<?php
function validateJsonSchema($json, $schema, $checkRequired=true)
{
$decodeIfNeeded=function ($maybeJson) {
if (is_string($maybeJson)) {
try {
return json_decode($maybeJson, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return false;
}
} else {
return $maybeJson;
}
};
$json = $decodeIfNeeded($json);
$schema = $decodeIfNeeded($schema);
if (!$json||!$schema) {
return("failed to decode json");
}
if (is_string($schema)) {
try {
$schema=json_decode($schema, false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
return "schema cannot be decoded";
}
}
if ($checkRequired) {
$missingRequiredKeys=[];
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "required")
&&$schemaValue->required) {
$missingRequiredKeys[]=$schemaKey;
}
}
}
foreach ($json as $jsonKey => $jsonValue) {
$type=gettype($jsonValue);
if ($type=="object") {//Needed to handle array situations
foreach ($schema as $schemaKey => $schemaValue) {
if (!property_exists($schemaValue, "type")
||!is_string($schemaValue->type)) {
$res=validateJsonSchema($jsonValue, $schemaValue, $checkRequired);
if ($res!="") {
return $res;
}
}
}
} else {
$schemaProperties=null;
if (!is_array($schema)) {
if ($checkRequired) {
$missingKey = array_search($jsonKey, $missingRequiredKeys, true);
if ($missingKey!== false) {
unset($missingRequiredKeys[$missingKey]);
}
}
if (!is_array($schema)&&!property_exists($schema, $jsonKey)) {
return "key not in schema";
}
$schemaProperties=$schema->$jsonKey;
} else {
foreach ($schema as $schemaKey => $schemaValue) {
if (property_exists($schemaValue, "type")
&&is_string($schemaValue->type)) {//This is a single value within an array
if ($type==$schemaValue->type) {
$schemaProperties=$schemaValue;
break;
}
}
}
}
if (!(is_null($jsonValue)&&property_exists($schemaProperties, "nullable")&&$schemaProperties->nullable)) {
if (is_null($schemaProperties)) {
return "type not allowed: ".$type;
}
if ($schemaProperties->type!=$type) {
if (!($type=="integer"&&$schemaProperties->type=="double")) {//integer instead of double is acceptable
return "type mismatch, expected: ".$schemaProperties->type." instead of ".$type." for ".$jsonKey;
}
}
$getSchemaProperty=function ($schemaProperties, $name) {
if (property_exists($schemaProperties, $name)) {
return $schemaProperties->$name;
}
if ($name=="min") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MIN;
}
return PHP_INT_MIN;
}
if ($name=="max") {
if ($schemaProperties->type=="double") {
return PHP_FLOAT_MAX;
}
return PHP_INT_MAX;
}
return null;
};
switch ($schemaProperties->type) {
case "string":
$count=strlen($jsonValue);
break;
case "integer":
case "double":
$count=$jsonValue;
break;
case "boolean":
$count=0;
break;
case "array":
$res=validateJsonSchema($jsonValue, $getSchemaProperty($schemaProperties, "data"), $checkRequired);
if ($res!="") {
return $res;
}
$count=count($jsonValue);
break;
default:
return "unknown type ".$schemaProperties->type;
break;
}
$min=$getSchemaProperty($schemaProperties, "min");
$max=$getSchemaProperty($schemaProperties, "max");
if ($count<$min) {
return "too short";
}
if ($count>$max) {
return "too long";
}
}
}
}
if ($checkRequired&&count($missingRequiredKeys)>0) {
return "missing required key(s)";
}
return "";
}
$json='
{
"a_string":"not short",
"a_number":null,
"a_double":3.14159265359,
"a_boolean":true,
"an_array":[
"no name",
3.14,
true,
{
"a_string2":"not short",
"a_number2":4
}
]
}
';
$schema='
{
"a_string":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number":{
"type":"integer",
"min":3,
"max":10,
"required":true,
"nullable":true
},
"a_double":{
"type":"double",
"min":3,
"max":10,
"required":true,
"nullable":false
},
"a_boolean":{
"type":"boolean",
"required":true
},
"an_array":{
"type":"array",
"min":2,
"max":10,
"required":false,
"data":
[
{
"type":"string",
"min":3,
"max":10
},
{
"type":"double",
"min":3,
"max":10
},
{
"type":"boolean"
},
{
"a_string2":{
"type":"string",
"min":3,
"max":10,
"required":true
},
"a_number2":{
"type":"integer",
"min":3,
"max":10,
"required":true
}
}
]
}
}
';
echo(validateJsonSchema($json, $schema)."\n");
?>
Loading
lang-php