ex
Fork of mbed-os-example-mbed5-blinky by
dumi_doc-master/schema/vendor/justinrainbow/json-schema/bin/validate-json@44:c1d8923072ba, 2017-07-18 (annotated)
- Committer:
- TMBOY
- Date:
- Tue Jul 18 16:27:22 2017 +0800
- Revision:
- 44:c1d8923072ba
?
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| TMBOY | 44:c1d8923072ba | 1 | #!/usr/bin/env php |
| TMBOY | 44:c1d8923072ba | 2 | <?php |
| TMBOY | 44:c1d8923072ba | 3 | /** |
| TMBOY | 44:c1d8923072ba | 4 | * JSON schema validator |
| TMBOY | 44:c1d8923072ba | 5 | * |
| TMBOY | 44:c1d8923072ba | 6 | * @author Christian Weiske <christian.weiske@netresearch.de> |
| TMBOY | 44:c1d8923072ba | 7 | */ |
| TMBOY | 44:c1d8923072ba | 8 | |
| TMBOY | 44:c1d8923072ba | 9 | /** |
| TMBOY | 44:c1d8923072ba | 10 | * Dead simple autoloader |
| TMBOY | 44:c1d8923072ba | 11 | * |
| TMBOY | 44:c1d8923072ba | 12 | * @param string $className Name of class to load |
| TMBOY | 44:c1d8923072ba | 13 | * |
| TMBOY | 44:c1d8923072ba | 14 | * @return void |
| TMBOY | 44:c1d8923072ba | 15 | */ |
| TMBOY | 44:c1d8923072ba | 16 | function __autoload($className) |
| TMBOY | 44:c1d8923072ba | 17 | { |
| TMBOY | 44:c1d8923072ba | 18 | $className = ltrim($className, '\\'); |
| TMBOY | 44:c1d8923072ba | 19 | $fileName = ''; |
| TMBOY | 44:c1d8923072ba | 20 | $namespace = ''; |
| TMBOY | 44:c1d8923072ba | 21 | if ($lastNsPos = strrpos($className, '\\')) { |
| TMBOY | 44:c1d8923072ba | 22 | $namespace = substr($className, 0, $lastNsPos); |
| TMBOY | 44:c1d8923072ba | 23 | $className = substr($className, $lastNsPos + 1); |
| TMBOY | 44:c1d8923072ba | 24 | $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; |
| TMBOY | 44:c1d8923072ba | 25 | } |
| TMBOY | 44:c1d8923072ba | 26 | $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; |
| TMBOY | 44:c1d8923072ba | 27 | if (stream_resolve_include_path($fileName)) { |
| TMBOY | 44:c1d8923072ba | 28 | require_once $fileName; |
| TMBOY | 44:c1d8923072ba | 29 | } |
| TMBOY | 44:c1d8923072ba | 30 | } |
| TMBOY | 44:c1d8923072ba | 31 | |
| TMBOY | 44:c1d8923072ba | 32 | /** |
| TMBOY | 44:c1d8923072ba | 33 | * Show the json parse error that happened last |
| TMBOY | 44:c1d8923072ba | 34 | * |
| TMBOY | 44:c1d8923072ba | 35 | * @return void |
| TMBOY | 44:c1d8923072ba | 36 | */ |
| TMBOY | 44:c1d8923072ba | 37 | function showJsonError() |
| TMBOY | 44:c1d8923072ba | 38 | { |
| TMBOY | 44:c1d8923072ba | 39 | $constants = get_defined_constants(true); |
| TMBOY | 44:c1d8923072ba | 40 | $json_errors = array(); |
| TMBOY | 44:c1d8923072ba | 41 | foreach ($constants['json'] as $name => $value) { |
| TMBOY | 44:c1d8923072ba | 42 | if (!strncmp($name, 'JSON_ERROR_', 11)) { |
| TMBOY | 44:c1d8923072ba | 43 | $json_errors[$value] = $name; |
| TMBOY | 44:c1d8923072ba | 44 | } |
| TMBOY | 44:c1d8923072ba | 45 | } |
| TMBOY | 44:c1d8923072ba | 46 | |
| TMBOY | 44:c1d8923072ba | 47 | echo 'JSON parse error: ' . $json_errors[json_last_error()] . "\n"; |
| TMBOY | 44:c1d8923072ba | 48 | } |
| TMBOY | 44:c1d8923072ba | 49 | |
| TMBOY | 44:c1d8923072ba | 50 | function getUrlFromPath($path) |
| TMBOY | 44:c1d8923072ba | 51 | { |
| TMBOY | 44:c1d8923072ba | 52 | if (parse_url($path, PHP_URL_SCHEME) !== null) { |
| TMBOY | 44:c1d8923072ba | 53 | //already an URL |
| TMBOY | 44:c1d8923072ba | 54 | return $path; |
| TMBOY | 44:c1d8923072ba | 55 | } |
| TMBOY | 44:c1d8923072ba | 56 | if ($path{0} == '/') { |
| TMBOY | 44:c1d8923072ba | 57 | //absolute path |
| TMBOY | 44:c1d8923072ba | 58 | return 'file://' . $path; |
| TMBOY | 44:c1d8923072ba | 59 | } |
| TMBOY | 44:c1d8923072ba | 60 | |
| TMBOY | 44:c1d8923072ba | 61 | //relative path: make absolute |
| TMBOY | 44:c1d8923072ba | 62 | return 'file://' . getcwd() . '/' . $path; |
| TMBOY | 44:c1d8923072ba | 63 | } |
| TMBOY | 44:c1d8923072ba | 64 | |
| TMBOY | 44:c1d8923072ba | 65 | /** |
| TMBOY | 44:c1d8923072ba | 66 | * Take a HTTP header value and split it up into parts. |
| TMBOY | 44:c1d8923072ba | 67 | * |
| TMBOY | 44:c1d8923072ba | 68 | * @param $headerValue |
| TMBOY | 44:c1d8923072ba | 69 | * @return array Key "_value" contains the main value, all others |
| TMBOY | 44:c1d8923072ba | 70 | * as given in the header value |
| TMBOY | 44:c1d8923072ba | 71 | */ |
| TMBOY | 44:c1d8923072ba | 72 | function parseHeaderValue($headerValue) |
| TMBOY | 44:c1d8923072ba | 73 | { |
| TMBOY | 44:c1d8923072ba | 74 | if (strpos($headerValue, ';') === false) { |
| TMBOY | 44:c1d8923072ba | 75 | return array('_value' => $headerValue); |
| TMBOY | 44:c1d8923072ba | 76 | } |
| TMBOY | 44:c1d8923072ba | 77 | |
| TMBOY | 44:c1d8923072ba | 78 | $parts = explode(';', $headerValue); |
| TMBOY | 44:c1d8923072ba | 79 | $arData = array('_value' => array_shift($parts)); |
| TMBOY | 44:c1d8923072ba | 80 | foreach ($parts as $part) { |
| TMBOY | 44:c1d8923072ba | 81 | list($name, $value) = explode('=', $part); |
| TMBOY | 44:c1d8923072ba | 82 | $arData[$name] = trim($value, ' "\''); |
| TMBOY | 44:c1d8923072ba | 83 | } |
| TMBOY | 44:c1d8923072ba | 84 | return $arData; |
| TMBOY | 44:c1d8923072ba | 85 | } |
| TMBOY | 44:c1d8923072ba | 86 | |
| TMBOY | 44:c1d8923072ba | 87 | |
| TMBOY | 44:c1d8923072ba | 88 | // support running this tool from git checkout |
| TMBOY | 44:c1d8923072ba | 89 | if (is_dir(__DIR__ . '/../src/JsonSchema')) { |
| TMBOY | 44:c1d8923072ba | 90 | set_include_path(__DIR__ . '/../src' . PATH_SEPARATOR . get_include_path()); |
| TMBOY | 44:c1d8923072ba | 91 | } |
| TMBOY | 44:c1d8923072ba | 92 | |
| TMBOY | 44:c1d8923072ba | 93 | $arOptions = array(); |
| TMBOY | 44:c1d8923072ba | 94 | $arArgs = array(); |
| TMBOY | 44:c1d8923072ba | 95 | array_shift($argv);//script itself |
| TMBOY | 44:c1d8923072ba | 96 | foreach ($argv as $arg) { |
| TMBOY | 44:c1d8923072ba | 97 | if ($arg{0} == '-') { |
| TMBOY | 44:c1d8923072ba | 98 | $arOptions[$arg] = true; |
| TMBOY | 44:c1d8923072ba | 99 | } else { |
| TMBOY | 44:c1d8923072ba | 100 | $arArgs[] = $arg; |
| TMBOY | 44:c1d8923072ba | 101 | } |
| TMBOY | 44:c1d8923072ba | 102 | } |
| TMBOY | 44:c1d8923072ba | 103 | |
| TMBOY | 44:c1d8923072ba | 104 | if (count($arArgs) == 0 |
| TMBOY | 44:c1d8923072ba | 105 | || isset($arOptions['--help']) || isset($arOptions['-h']) |
| TMBOY | 44:c1d8923072ba | 106 | ) { |
| TMBOY | 44:c1d8923072ba | 107 | echo <<<HLP |
| TMBOY | 44:c1d8923072ba | 108 | Validate schema |
| TMBOY | 44:c1d8923072ba | 109 | Usage: validate-json data.json |
| TMBOY | 44:c1d8923072ba | 110 | or: validate-json data.json schema.json |
| TMBOY | 44:c1d8923072ba | 111 | |
| TMBOY | 44:c1d8923072ba | 112 | Options: |
| TMBOY | 44:c1d8923072ba | 113 | --dump-schema Output full schema and exit |
| TMBOY | 44:c1d8923072ba | 114 | --dump-schema-url Output URL of schema |
| TMBOY | 44:c1d8923072ba | 115 | -h --help Show this help |
| TMBOY | 44:c1d8923072ba | 116 | |
| TMBOY | 44:c1d8923072ba | 117 | HLP; |
| TMBOY | 44:c1d8923072ba | 118 | exit(1); |
| TMBOY | 44:c1d8923072ba | 119 | } |
| TMBOY | 44:c1d8923072ba | 120 | |
| TMBOY | 44:c1d8923072ba | 121 | if (count($arArgs) == 1) { |
| TMBOY | 44:c1d8923072ba | 122 | $pathData = $arArgs[0]; |
| TMBOY | 44:c1d8923072ba | 123 | $pathSchema = null; |
| TMBOY | 44:c1d8923072ba | 124 | } else { |
| TMBOY | 44:c1d8923072ba | 125 | $pathData = $arArgs[0]; |
| TMBOY | 44:c1d8923072ba | 126 | $pathSchema = getUrlFromPath($arArgs[1]); |
| TMBOY | 44:c1d8923072ba | 127 | } |
| TMBOY | 44:c1d8923072ba | 128 | |
| TMBOY | 44:c1d8923072ba | 129 | $urlData = getUrlFromPath($pathData); |
| TMBOY | 44:c1d8923072ba | 130 | |
| TMBOY | 44:c1d8923072ba | 131 | $context = stream_context_create( |
| TMBOY | 44:c1d8923072ba | 132 | array( |
| TMBOY | 44:c1d8923072ba | 133 | 'http' => array( |
| TMBOY | 44:c1d8923072ba | 134 | 'header' => array( |
| TMBOY | 44:c1d8923072ba | 135 | 'Accept: */*', |
| TMBOY | 44:c1d8923072ba | 136 | 'Connection: Close' |
| TMBOY | 44:c1d8923072ba | 137 | ), |
| TMBOY | 44:c1d8923072ba | 138 | 'max_redirects' => 5 |
| TMBOY | 44:c1d8923072ba | 139 | ) |
| TMBOY | 44:c1d8923072ba | 140 | ) |
| TMBOY | 44:c1d8923072ba | 141 | ); |
| TMBOY | 44:c1d8923072ba | 142 | $dataString = file_get_contents($pathData, false, $context); |
| TMBOY | 44:c1d8923072ba | 143 | if ($dataString == '') { |
| TMBOY | 44:c1d8923072ba | 144 | echo "Data file is not readable or empty.\n"; |
| TMBOY | 44:c1d8923072ba | 145 | exit(3); |
| TMBOY | 44:c1d8923072ba | 146 | } |
| TMBOY | 44:c1d8923072ba | 147 | |
| TMBOY | 44:c1d8923072ba | 148 | $data = json_decode($dataString); |
| TMBOY | 44:c1d8923072ba | 149 | unset($dataString); |
| TMBOY | 44:c1d8923072ba | 150 | if ($data === null) { |
| TMBOY | 44:c1d8923072ba | 151 | echo "Error loading JSON data file\n"; |
| TMBOY | 44:c1d8923072ba | 152 | showJsonError(); |
| TMBOY | 44:c1d8923072ba | 153 | exit(5); |
| TMBOY | 44:c1d8923072ba | 154 | } |
| TMBOY | 44:c1d8923072ba | 155 | |
| TMBOY | 44:c1d8923072ba | 156 | if ($pathSchema === null) { |
| TMBOY | 44:c1d8923072ba | 157 | if (isset($http_response_header)) { |
| TMBOY | 44:c1d8923072ba | 158 | array_shift($http_response_header);//HTTP/1.0 line |
| TMBOY | 44:c1d8923072ba | 159 | foreach ($http_response_header as $headerLine) { |
| TMBOY | 44:c1d8923072ba | 160 | list($hName, $hValue) = explode(':', $headerLine, 2); |
| TMBOY | 44:c1d8923072ba | 161 | $hName = strtolower($hName); |
| TMBOY | 44:c1d8923072ba | 162 | if ($hName == 'link') { |
| TMBOY | 44:c1d8923072ba | 163 | //Link: <http://example.org/schema#>; rel="describedBy" |
| TMBOY | 44:c1d8923072ba | 164 | $hParts = parseHeaderValue($hValue); |
| TMBOY | 44:c1d8923072ba | 165 | if (isset($hParts['rel']) && $hParts['rel'] == 'describedBy') { |
| TMBOY | 44:c1d8923072ba | 166 | $pathSchema = trim($hParts['_value'], ' <>'); |
| TMBOY | 44:c1d8923072ba | 167 | } |
| TMBOY | 44:c1d8923072ba | 168 | } else if ($hName == 'content-type') { |
| TMBOY | 44:c1d8923072ba | 169 | //Content-Type: application/my-media-type+json; |
| TMBOY | 44:c1d8923072ba | 170 | // profile=http://example.org/schema# |
| TMBOY | 44:c1d8923072ba | 171 | $hParts = parseHeaderValue($hValue); |
| TMBOY | 44:c1d8923072ba | 172 | if (isset($hParts['profile'])) { |
| TMBOY | 44:c1d8923072ba | 173 | $pathSchema = $hParts['profile']; |
| TMBOY | 44:c1d8923072ba | 174 | } |
| TMBOY | 44:c1d8923072ba | 175 | |
| TMBOY | 44:c1d8923072ba | 176 | } |
| TMBOY | 44:c1d8923072ba | 177 | } |
| TMBOY | 44:c1d8923072ba | 178 | } |
| TMBOY | 44:c1d8923072ba | 179 | if (is_object($data) && property_exists($data, '$schema')) { |
| TMBOY | 44:c1d8923072ba | 180 | $pathSchema = $data->{'$schema'}; |
| TMBOY | 44:c1d8923072ba | 181 | } |
| TMBOY | 44:c1d8923072ba | 182 | |
| TMBOY | 44:c1d8923072ba | 183 | //autodetect schema |
| TMBOY | 44:c1d8923072ba | 184 | if ($pathSchema === null) { |
| TMBOY | 44:c1d8923072ba | 185 | echo "JSON data must be an object and have a \$schema property.\n"; |
| TMBOY | 44:c1d8923072ba | 186 | echo "You can pass the schema file on the command line as well.\n"; |
| TMBOY | 44:c1d8923072ba | 187 | echo "Schema autodetection failed.\n"; |
| TMBOY | 44:c1d8923072ba | 188 | exit(6); |
| TMBOY | 44:c1d8923072ba | 189 | } |
| TMBOY | 44:c1d8923072ba | 190 | } |
| TMBOY | 44:c1d8923072ba | 191 | if ($pathSchema{0} == '/') { |
| TMBOY | 44:c1d8923072ba | 192 | $pathSchema = 'file://' . $pathSchema; |
| TMBOY | 44:c1d8923072ba | 193 | } |
| TMBOY | 44:c1d8923072ba | 194 | |
| TMBOY | 44:c1d8923072ba | 195 | $resolver = new JsonSchema\Uri\UriResolver(); |
| TMBOY | 44:c1d8923072ba | 196 | $retriever = new JsonSchema\Uri\UriRetriever(); |
| TMBOY | 44:c1d8923072ba | 197 | try { |
| TMBOY | 44:c1d8923072ba | 198 | $urlSchema = $resolver->resolve($pathSchema, $urlData); |
| TMBOY | 44:c1d8923072ba | 199 | |
| TMBOY | 44:c1d8923072ba | 200 | if (isset($arOptions['--dump-schema-url'])) { |
| TMBOY | 44:c1d8923072ba | 201 | echo $urlSchema . "\n"; |
| TMBOY | 44:c1d8923072ba | 202 | exit(); |
| TMBOY | 44:c1d8923072ba | 203 | } |
| TMBOY | 44:c1d8923072ba | 204 | } catch (Exception $e) { |
| TMBOY | 44:c1d8923072ba | 205 | echo "Error loading JSON schema file\n"; |
| TMBOY | 44:c1d8923072ba | 206 | echo $urlSchema . "\n"; |
| TMBOY | 44:c1d8923072ba | 207 | echo $e->getMessage() . "\n"; |
| TMBOY | 44:c1d8923072ba | 208 | exit(2); |
| TMBOY | 44:c1d8923072ba | 209 | } |
| TMBOY | 44:c1d8923072ba | 210 | $refResolver = new JsonSchema\RefResolver($retriever, $resolver); |
| TMBOY | 44:c1d8923072ba | 211 | $schema = $refResolver->resolve($urlSchema); |
| TMBOY | 44:c1d8923072ba | 212 | |
| TMBOY | 44:c1d8923072ba | 213 | if (isset($arOptions['--dump-schema'])) { |
| TMBOY | 44:c1d8923072ba | 214 | $options = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0; |
| TMBOY | 44:c1d8923072ba | 215 | echo json_encode($schema, $options) . "\n"; |
| TMBOY | 44:c1d8923072ba | 216 | exit(); |
| TMBOY | 44:c1d8923072ba | 217 | } |
| TMBOY | 44:c1d8923072ba | 218 | |
| TMBOY | 44:c1d8923072ba | 219 | try { |
| TMBOY | 44:c1d8923072ba | 220 | $validator = new JsonSchema\Validator(); |
| TMBOY | 44:c1d8923072ba | 221 | $validator->check($data, $schema); |
| TMBOY | 44:c1d8923072ba | 222 | |
| TMBOY | 44:c1d8923072ba | 223 | if ($validator->isValid()) { |
| TMBOY | 44:c1d8923072ba | 224 | echo "OK. The supplied JSON validates against the schema.\n"; |
| TMBOY | 44:c1d8923072ba | 225 | } else { |
| TMBOY | 44:c1d8923072ba | 226 | echo "JSON does not validate. Violations:\n"; |
| TMBOY | 44:c1d8923072ba | 227 | foreach ($validator->getErrors() as $error) { |
| TMBOY | 44:c1d8923072ba | 228 | echo sprintf("[%s] %s\n", $error['property'], $error['message']); |
| TMBOY | 44:c1d8923072ba | 229 | } |
| TMBOY | 44:c1d8923072ba | 230 | exit(23); |
| TMBOY | 44:c1d8923072ba | 231 | } |
| TMBOY | 44:c1d8923072ba | 232 | } catch (Exception $e) { |
| TMBOY | 44:c1d8923072ba | 233 | echo "JSON does not validate. Error:\n"; |
| TMBOY | 44:c1d8923072ba | 234 | echo $e->getMessage() . "\n"; |
| TMBOY | 44:c1d8923072ba | 235 | echo "Error code: " . $e->getCode() . "\n"; |
| TMBOY | 44:c1d8923072ba | 236 | exit(24); |
| TMBOY | 44:c1d8923072ba | 237 | } |
