Skip to content

Commit fdf1e75

Browse files
author
bruno_p_reis
committed
beta 2 version with complete functionalities and selenium test suite
git-svn-id: https://jsonschemaphpv.svn.sourceforge.net/svnroot/jsonschemaphpv/trunk@1 14558f9d-7ea9-46ec-92da-52a2cad6a683
0 parents  commit fdf1e75

28 files changed

+3342
-0
lines changed

JsSchema.php

Lines changed: 410 additions & 0 deletions
Large diffs are not rendered by default.

functions.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
function print_r( array, return_val ) {
2+
// http://kevin.vanzonneveld.net
3+
// + original by: Michael White (http://getsprink.com)
4+
// + improved by: Ben Bryan
5+
// * example 1: print_r(1, true);
6+
// * returns 1: 1
7+
8+
var output = "", pad_char = " ", pad_val = 4;
9+
10+
var formatArray = function (obj, cur_depth, pad_val, pad_char) {
11+
if (cur_depth > 0) {
12+
cur_depth++;
13+
}
14+
15+
var base_pad = repeat_char(pad_val*cur_depth, pad_char);
16+
var thick_pad = repeat_char(pad_val*(cur_depth+1), pad_char);
17+
var str = "";
18+
19+
if (obj instanceof Array || obj instanceof Object) {
20+
str += "Array\n" + base_pad + "(\n";
21+
for (var key in obj) {
22+
if (obj[key] instanceof Array) {
23+
str += thick_pad + "["+key+"] => "+formatArray(obj[key], cur_depth+1, pad_val, pad_char);
24+
} else {
25+
str += thick_pad + "["+key+"] => " + obj[key] + "\n";
26+
}
27+
}
28+
str += base_pad + ")\n";
29+
} else if(obj == null || obj == undefined) {
30+
str = '';
31+
} else {
32+
str = obj.toString();
33+
}
34+
35+
return str;
36+
};
37+
38+
var repeat_char = function (len, pad_char) {
39+
var str = "";
40+
for(var i=0; i < len; i++) {
41+
str += pad_char;
42+
};
43+
return str;
44+
};
45+
output = formatArray(array, 0, pad_val, pad_char);
46+
47+
if (return_val !== true) {
48+
document.write("<pre>" + output + "</pre>");
49+
return true;
50+
} else {
51+
return output;
52+
}
53+
}

interface.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
*{
2+
font-family: verdana, arial, sans-serif;
3+
}
4+
.campo{
5+
width:550px;
6+
height:230px;
7+
background-color:#eee;
8+
}
9+
.botao{
10+
width:300px;
11+
height:60px;
12+
}
13+
.comment{
14+
background-color:#eee;
15+
color:#363;
16+
font-size: .7em;
17+
}

interface.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
$(document).ready(function(){
2+
$("#bt-validate-js").click(validateJs);
3+
$("#bt-validate-php").click(validatePhp);
4+
});
5+
6+
7+
function validatePhp() {
8+
$('#resultados').html('. . . w o r k i n g . . . ');
9+
schema = $('#schema').val();
10+
json = $('#json').val();
11+
12+
$.getJSON(
13+
"validate.php",
14+
{"schema":schema,"json":json},
15+
phpCallback
16+
);
17+
}
18+
19+
function phpCallback(json) {
20+
showResponse(json);
21+
}
22+
23+
function validateJs() {
24+
$('#resultados').html('. . . w o r k i n g . . . ');
25+
jsons = getJsons();
26+
//alert(print_r(jsons,true));
27+
if(jsons.schema) {
28+
validateResponse = JSONSchema.validate(jsons.json,jsons.schema);
29+
}
30+
else {
31+
validateResponse = JSONSchema.validate(jsons.json);
32+
}
33+
showResponse(validateResponse);
34+
}
35+
36+
function getJsons() {
37+
schema = $('#schema').val();
38+
json = $('#json').val();
39+
json = eval( '(' + json + ')' );
40+
if(schema) {
41+
schema = eval( '(' + schema + ')' );
42+
}
43+
return {"json":json,"schema":schema};
44+
}
45+
46+
function showResponse(validateResponse) {
47+
//alert(print_r(validateResponse,true));
48+
res = '<b>'+'JSON: '+(validateResponse.valid?' VALID':'INVALID')+'</B><BR/>';
49+
$.each(validateResponse.errors,function(i,item) {
50+
//alert(print_r(item,true));
51+
res += '<b>' + item.property + '</b> :: ' + item.message + '<br/><br/>';
52+
res += '<span class=comment>'+(i+":"+print_r(item,true))+"</span><BR/><br/>";
53+
});
54+
$('#resultados').html(res);
55+
}

jquery.js

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jsonschema.js

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/**
2+
* JSONSchema Validator - Validates JavaScript objects using JSON Schemas
3+
* (http://www.json.com/json-schema-proposal/)
4+
*
5+
* Copyright (c) 2007 Kris Zyp SitePen (www.sitepen.com)
6+
* Licensed under the MIT (MIT-LICENSE.txt) licence.
7+
To use the validator call JSONSchema.validate with an instance object and an optional schema object.
8+
If a schema is provided, it will be used to validate. If the instance object refers to a schema (self-validating),
9+
that schema will be used to validate and the schema parameter is not necessary (if both exist,
10+
both validations will occur).
11+
The validate method will return an array of validation errors. If there are no errors, then an
12+
empty list will be returned. A validation error will have two properties:
13+
"property" which indicates which property had the error
14+
"message" which indicates what the error was
15+
*/
16+
17+
JSONSchema = {
18+
validate : function(/*Any*/instance,/*Object*/schema) {
19+
// Summary:
20+
// To use the validator call JSONSchema.validate with an instance object and an optional schema object.
21+
// If a schema is provided, it will be used to validate. If the instance object refers to a schema (self-validating),
22+
// that schema will be used to validate and the schema parameter is not necessary (if both exist,
23+
// both validations will occur).
24+
// The validate method will return an object with two properties:
25+
// valid: A boolean indicating if the instance is valid by the schema
26+
// errors: An array of validation errors. If there are no errors, then an
27+
// empty list will be returned. A validation error will have two properties:
28+
// property: which indicates which property had the error
29+
// message: which indicates what the error was
30+
//
31+
return this._validate(instance,schema,false);
32+
},
33+
checkPropertyChange : function(/*Any*/value,/*Object*/schema) {
34+
// Summary:
35+
// The checkPropertyChange method will check to see if an value can legally be in property with the given schema
36+
// This is slightly different than the validate method in that it will fail if the schema is readonly and it will
37+
// not check for self-validation, it is assumed that the passed in value is already internally valid.
38+
// The checkPropertyChange method will return the same object type as validate, see JSONSchema.validate for
39+
// information.
40+
//
41+
return this._validate(value,schema,true);
42+
},
43+
_validate : function(/*Any*/instance,/*Object*/schema,/*Boolean*/ _changing) {
44+
45+
46+
var errors2 = [];
47+
// validate a value against a property definition
48+
49+
function checkProp(value, schema, path,i) {
50+
if (typeof schema != 'object') {
51+
return;
52+
}
53+
path += path ? typeof i == 'number' ? '[' + i + ']' : typeof i == 'undefined' ? '' : '.' + i : i;
54+
function addError(message) {
55+
errors2.push({property:path,message:message});
56+
}
57+
if (_changing && schema.readonly)
58+
addError("is a readonly field, it can not be changed");
59+
/*
60+
if (schema instanceof Array) {
61+
if (!(value instanceof Array)) {
62+
return [{property:path,message:"An array tuple is required"}];
63+
}
64+
for (i =0; i < schema.length; i++) {
65+
errors2.concat(checkProp(value[i],schema[i],path,i));
66+
}
67+
return errors2;
68+
}
69+
*/
70+
if (schema['extends']) // if it extends another schema, it must pass that schema as well
71+
checkProp(value,schema['extends'],path,i);
72+
// validate a value against a type definition
73+
function checkType(type,value) {
74+
if (type) {
75+
if (typeof type == 'string' && type != 'any'
76+
&& (type == 'null' ? value !== null : typeof value != type)
77+
&& !(value instanceof Array && type == 'array')
78+
&& !(type == 'integer' && !(value%1)))
79+
return [{property:path,message:(typeof value) + " value found, but a " + type + " is required"}];
80+
if (type instanceof Array) {
81+
var unionErrors=[];
82+
for (var j = 0; j < type.length; j++) // a union type
83+
if (!(unionErrors=checkType(type[j],value)).length)
84+
break;
85+
if (unionErrors.length)
86+
return unionErrors;
87+
}
88+
else if (typeof type == 'object') {
89+
checkProp(value,type,path);
90+
}
91+
}
92+
return [];
93+
}
94+
95+
//if (value !== null) {
96+
if (value === undefined) {
97+
if (!schema.optional)
98+
addError("is missing and it is not optional");
99+
}
100+
else {
101+
errors2 = errors2.concat(checkType(schema.type,value));
102+
if (schema.disallow && !checkType(schema.disallow,value).length)
103+
addError(" disallowed value was matched");
104+
if (value instanceof Array) {
105+
if (schema.items) {
106+
if(schema.items instanceof Array) {
107+
for (var k = 0,l=value.length; k < l; k++) {
108+
if(k < schema.items.length) {
109+
errors2.concat(checkProp(value[k],schema.items[k],path,k));
110+
}
111+
else {
112+
if(schema.additionalProperties !== undefined) {
113+
if(schema.additionalProperties === false) {
114+
addError("The item " + i + "[" + k + "] is not defined in the objTypeDef and the objTypeDef does not allow additional properties");
115+
}
116+
else {
117+
errors2.concat(checkProp(value[k],schema.additionalProperties,path,k));
118+
}
119+
}
120+
}
121+
}
122+
if(value.length < schema.items.length) {
123+
for (var k = value.length; k < schema.items.length; k++) {
124+
errors2.concat(checkProp(undefined,schema.items[k],path,k));
125+
}
126+
}
127+
}
128+
else {
129+
for (var i =0,l=value.length; i < l; i++) {
130+
errors2.concat(checkProp(value[i],schema.items,path,i));
131+
}
132+
}
133+
}
134+
if (schema.minItems && value.length < schema.minItems) {
135+
addError("There must be a minimum of " + schema.minItems + " in the array");
136+
}
137+
if (schema.maxItems && value.length > schema.maxItems) {
138+
addError("There must be a maximum of " + schema.maxItems + " in the array");
139+
}
140+
}
141+
else if (schema.properties && typeof value == 'object') {
142+
errors2.concat(checkObj(value,schema.properties,path,schema.additionalProperties));
143+
}
144+
if (schema.pattern && typeof value == 'string' && !value.match(schema.pattern))
145+
addError("does not match the regex pattern " + schema.pattern);
146+
if (schema.maxLength && typeof value == 'string' && (value.length > schema.maxLength))
147+
addError("may only be " + schema.maxLength + " characters long");
148+
if (schema.minLength && typeof value == 'string' && (value.length < schema.minLength))
149+
addError("must be at least " + schema.minLength + " characters long");
150+
if (typeof schema.minimum !== undefined && typeof value == typeof schema.minimum && schema.minimum > value)
151+
addError("must have a minimum value of " + schema.minimum);
152+
if (typeof schema.maximum !== undefined && typeof value == typeof schema.maximum && schema.maximum < value)
153+
addError("must have a maximum value of " + schema.maximum);
154+
if (schema['enum']) {
155+
var enumer = schema['enum'];
156+
var l = enumer.length;
157+
var found;
158+
for (var j = 0; j < l; j++)
159+
if (enumer[j]===value) {
160+
found=1;
161+
break;
162+
}
163+
if (!found) {
164+
addError("does not have a value in the enumeration " + enumer.join(", "));
165+
}
166+
}
167+
if (typeof schema.maxDecimal == 'number' && (value * Math.pow(10,schema.maxDecimal))%1) {
168+
addError("may only have " + schema.maxDecimal + " digits of decimal places");
169+
}
170+
}
171+
//}
172+
173+
}
174+
// validate an object against a schema
175+
function checkObj(instance,objTypeDef,path,additionalProp) {
176+
if (typeof objTypeDef =='object') {
177+
if (typeof instance != 'object' || instance instanceof Array)
178+
errors2.push({property:path,message:"an object is required"});
179+
180+
for (var i in objTypeDef)
181+
if (objTypeDef.hasOwnProperty(i)) {
182+
var value = instance[i];
183+
var propDef = objTypeDef[i];
184+
checkProp(value,propDef,path,i);
185+
}
186+
}
187+
for (var i in instance) {
188+
if (instance.hasOwnProperty(i) && objTypeDef && !objTypeDef[i] && additionalProp===false)
189+
errors2.push({property:path,message:(typeof value) + "The property " + i + " is not defined in the objTypeDef and the objTypeDef does not allow additional properties"});
190+
var requires = objTypeDef && objTypeDef[i] && objTypeDef[i].requires;
191+
if (requires && !(requires in instance))
192+
errors2.push({property:path,message:"the presence of the property " + i + " requires that " + requires + " also be present"});
193+
value = instance[i];
194+
if (objTypeDef && typeof objTypeDef == 'object' && !(i in objTypeDef))
195+
checkProp(value,additionalProp,path,i);
196+
// if (!_changing && value && value.type)
197+
// errors2 = errors2.concat(checkObj(value,value.type,path + '.' + i));
198+
if (!_changing && value && value.$schema)
199+
errors2 = errors2.concat(checkProp(value,value.$schema,path,i));
200+
}
201+
return errors2;
202+
}
203+
if (schema)
204+
checkProp(instance,schema,'','')
205+
if (!_changing && instance.$schema)
206+
checkProp(instance,instance.$schema,'','');
207+
return {valid:!errors2.length,errors:errors2};
208+
}
209+
/* will add this later
210+
newFromSchema : function() {
211+
}
212+
*/
213+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4+
<head>
5+
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
6+
<title>Test Suite</title>
7+
</head>
8+
<body>
9+
<table id="suiteTable" cellpadding="1" cellspacing="1" border="1" class="selenium"><tbody>
10+
<tr><td><b>Test Suite</b></td></tr>
11+
<tr><td><a href="basicTypes">basicTypes</a></td></tr>
12+
<tr><td><a href="unionTypes">unionTypes</a></td></tr>
13+
<tr><td><a href="unionWithNullValue">unionWithNullValue</a></td></tr>
14+
<tr><td><a href="arrays">arrays</a></td></tr>
15+
<tr><td><a href="tupleTyping">tupleTyping</a></td></tr>
16+
<tr><td><a href="numberAndIntegerTypes">numberAndIntegerTypes</a></td></tr>
17+
<tr><td><a href="optionalProperty">optionalProperty</a></td></tr>
18+
<tr><td><a href="additionalProperties">additionalProperties</a></td></tr>
19+
<tr><td><a href="require">require</a></td></tr>
20+
<tr><td><a href="minimumMaximum">minimumMaximum</a></td></tr>
21+
<tr><td><a href="minItemsMaxItems">minItemsMaxItems</a></td></tr>
22+
<tr><td><a href="minLengthMaxLength">minLengthMaxLength</a></td></tr>
23+
<tr><td><a href="pattern">pattern</a></td></tr>
24+
<tr><td><a href="enum">enum</a></td></tr>
25+
<tr><td><a href="maxDecimal">maxDecimal</a></td></tr>
26+
<tr><td><a href="selfDefinedSchema">selfDefinedSchema</a></td></tr>
27+
<tr><td><a href="extends">extends</a></td></tr>
28+
<tr><td><a href="disallow">disallow</a></td></tr>
29+
<tr><td><a href="wrongMessagesFailingTestCase">wrongMessagesFailingTestCase</a></td></tr>
30+
</tbody></table>
31+
</body>
32+
</html>

0 commit comments

Comments
 (0)