@@ -24,7 +24,9 @@ function __autoload($className)
2424 $ fileName = str_replace ('\\' , DIRECTORY_SEPARATOR , $ namespace ) . DIRECTORY_SEPARATOR ;
2525 }
2626 $ fileName .= str_replace ('_ ' , DIRECTORY_SEPARATOR , $ className ) . '.php ' ;
27- require_once $ fileName ;
27+ if (stream_resolve_include_path ($ fileName )) {
28+ require_once $ fileName ;
29+ }
2830}
2931
3032/**
@@ -45,55 +47,198 @@ function showJsonError()
4547 echo 'JSON parse error: ' . $ json_errors [json_last_error ()] . "\n" ;
4648}
4749
50+ function getUrlFromPath ($ path )
51+ {
52+ if (parse_url ($ path , PHP_URL_SCHEME ) !== null ) {
53+ //already an URL
54+ return $ path ;
55+ }
56+ if ($ path {0 } == '/ ' ) {
57+ //absolute path
58+ return 'file:// ' . $ path ;
59+ }
60+
61+ //relative path: make absolute
62+ return 'file:// ' . getcwd () . '/ ' . $ path ;
63+ }
64+
65+ /**
66+ * Take a HTTP header value and split it up into parts.
67+ *
68+ * @return array Key "_value" contains the main value, all others
69+ * as given in the header value
70+ */
71+ function parseHeaderValue ($ headerValue )
72+ {
73+ if (strpos ($ headerValue , '; ' ) === false ) {
74+ return array ('_value ' => $ headerValue );
75+ }
76+
77+ $ parts = explode ('; ' , $ headerValue );
78+ $ arData = array ('_value ' => array_shift ($ parts ));
79+ foreach ($ parts as $ part ) {
80+ list ($ name , $ value ) = explode ('= ' , $ part );
81+ $ arData [$ name ] = trim ($ value , ' " \'' );
82+ }
83+ return $ arData ;
84+ }
85+
4886
4987// support running this tool from git checkout
5088if (is_dir (__DIR__ . '/../src/JsonSchema ' )) {
5189 set_include_path (__DIR__ . '/../src ' . PATH_SEPARATOR . get_include_path ());
5290}
5391
54- if ($ argc < 3 ) {
55- echo "Usage: validate-json schema.json data.json \n" ;
56- exit (1 );
92+ $ arOptions = array ();
93+ $ arArgs = array ();
94+ array_shift ($ argv );//script itself
95+ foreach ($ argv as $ arg ) {
96+ if ($ arg {0 } == '- ' ) {
97+ $ arOptions [$ arg ] = true ;
98+ } else {
99+ $ arArgs [] = $ arg ;
100+ }
57101}
58102
59- $ pathSchema = $ argv [1 ];
60- $ pathData = $ argv [2 ];
103+ if (count ($ arArgs ) == 0
104+ || isset ($ arOptions ['--help ' ]) || isset ($ arOptions ['-h ' ])
105+ ) {
106+ echo <<<HLP
107+ Validate schema
108+ Usage: validate-json data.json
109+ or: validate-json data.json schema.json
61110
62- if (!is_readable ($ pathSchema )) {
63- echo "Schema file is not readable. \n" ;
64- exit (2 );
111+ Options:
112+ --dump-schema Output full schema and exit
113+ --dump-schema-url Output URL of schema
114+ -h --help Show this help
115+
116+ HLP ;
117+ exit (1 );
65118}
66119
67- if (!is_readable ($ pathData )) {
68- echo "Data file is not readable. \n" ;
69- exit (3 );
120+ if (count ($ arArgs ) == 1 ) {
121+ $ pathData = $ arArgs [0 ];
122+ $ pathSchema = null ;
123+ } else {
124+ $ pathData = $ arArgs [0 ];
125+ $ pathSchema = getUrlFromPath ($ arArgs [1 ]);
70126}
71127
72- $ data = json_decode (file_get_contents ($ pathData ));
128+ $ urlData = getUrlFromPath ($ pathData );
129+
130+ $ context = stream_context_create (
131+ array (
132+ 'http ' => array (
133+ 'header ' => array (
134+ 'Accept: */* ' ,
135+ 'Connection: Close '
136+ ),
137+ 'max_redirects ' => 5
138+ )
139+ )
140+ );
141+ $ dataString = file_get_contents ($ pathData , false , $ context );
142+ if ($ dataString == '' ) {
143+ echo "Data file is not readable or empty. \n" ;
144+ exit (3 );
145+ }
73146
147+ $ data = json_decode ($ dataString );
148+ unset($ dataString );
74149if ($ data === null ) {
75150 echo "Error loading JSON data file \n" ;
76151 showJsonError ();
77152 exit (5 );
78153}
79154
80- $ schema = json_decode (file_get_contents ($ pathSchema ));
155+ if ($ pathSchema === null ) {
156+ if (isset ($ http_response_header )) {
157+ array_shift ($ http_response_header );//HTTP/1.0 line
158+ foreach ($ http_response_header as $ headerLine ) {
159+ list ($ hName , $ hValue ) = explode (': ' , $ headerLine , 2 );
160+ $ hName = strtolower ($ hName );
161+ if ($ hName == 'link ' ) {
162+ //Link: <http://example.org/schema#>; rel="describedBy"
163+ $ hParts = parseHeaderValue ($ hValue );
164+ if (isset ($ hParts ['rel ' ]) && $ hParts ['rel ' ] == 'describedBy ' ) {
165+ $ pathSchema = trim ($ hParts ['_value ' ], ' <> ' );
166+ }
167+ } else if ($ hName == 'content-type ' ) {
168+ //Content-Type: application/my-media-type+json;
169+ // profile=http://example.org/schema#
170+ $ hParts = parseHeaderValue ($ hValue );
171+ if (isset ($ hParts ['profile ' ])) {
172+ $ pathSchema = $ hParts ['profile ' ];
173+ }
174+
175+ }
176+ }
177+ }
178+ if (is_object ($ data ) && property_exists ($ data , '$schema ' )) {
179+ $ pathSchema = $ data ->{'$schema ' };
180+ }
181+
182+ //autodetect schema
183+ if ($ pathSchema === null ) {
184+ echo "JSON data must be an object and have a \$schema property. \n" ;
185+ echo "You can pass the schema file on the command line as well. \n" ;
186+ echo "Schema autodetection failed. \n" ;
187+ exit (6 );
188+ }
189+ }
190+ if ($ pathSchema {0 } == '/ ' ) {
191+ $ pathSchema = 'file:// ' . $ pathSchema ;
192+ }
193+
194+ $ resolver = new JsonSchema \Uri \UriResolver ();
195+ $ retriever = new JsonSchema \Uri \UriRetriever ();
196+ try {
197+ $ urlSchema = $ resolver ->resolve ($ pathSchema , $ urlData );
198+
199+ if (isset ($ arOptions ['--dump-schema-url ' ])) {
200+ echo $ urlSchema . "\n" ;
201+ exit ();
202+ }
81203
82- if ($ schema === null ) {
204+ $ schema = $ retriever ->retrieve ($ urlSchema );
205+ if ($ schema === null ) {
206+ echo "Error loading JSON schema file \n" ;
207+ echo $ urlSchema . "\n" ;
208+ showJsonError ();
209+ exit (2 );
210+ }
211+ } catch (Exception $ e ) {
83212 echo "Error loading JSON schema file \n" ;
84- showJsonError ();
85- exit (6 );
213+ echo $ urlSchema . "\n" ;
214+ echo $ e ->getMessage () . "\n" ;
215+ exit (2 );
86216}
217+ $ refResolver = new JsonSchema \RefResolver ($ retriever );
218+ $ refResolver ->resolve ($ schema , $ urlSchema );
87219
88- $ validator = new JsonSchema \Validator ();
89- $ validator ->check ($ data , $ schema );
220+ if (isset ($ arOptions ['--dump-schema ' ])) {
221+ echo json_encode ($ schema , JSON_PRETTY_PRINT ) . "\n" ;
222+ exit ();
223+ }
90224
91- if ($ validator ->isValid ()) {
92- echo "OK. The supplied JSON validates against the schema. \n" ;
93- } else {
94- echo "JSON does not validate. Violations: \n" ;
95- foreach ($ validator ->getErrors () as $ error ) {
96- echo sprintf ("[%s] %s \n" , $ error ['property ' ], $ error ['message ' ]);
225+ try {
226+ $ validator = new JsonSchema \Validator ();
227+ $ validator ->check ($ data , $ schema );
228+
229+ if ($ validator ->isValid ()) {
230+ echo "OK. The supplied JSON validates against the schema. \n" ;
231+ } else {
232+ echo "JSON does not validate. Violations: \n" ;
233+ foreach ($ validator ->getErrors () as $ error ) {
234+ echo sprintf ("[%s] %s \n" , $ error ['property ' ], $ error ['message ' ]);
235+ }
236+ exit (23 );
97237 }
98- exit (23 );
238+ } catch (Exception $ e ) {
239+ echo "JSON does not validate. Error: \n" ;
240+ echo $ e ->getMessage () . "\n" ;
241+ echo "Error code: " . $ e ->getCode () . "\n" ;
242+ exit (24 );
99243}
244+ ?>
0 commit comments