├── Dockerfile ├── src ├── ExitCode.php ├── FilePosition │ ├── PathState.php │ └── PositionResolver.php ├── JsonSchema │ └── ResolverMux.php ├── Rearrange.php ├── SchemaResolver.php ├── PrettyPrint.php ├── Minify.php ├── Resolve.php ├── Json │ └── LoadFile.php ├── Diff.php ├── BaseDiff.php ├── GenPhp │ └── BuilderOptions.php ├── DiffInfo.php ├── GenJSDoc.php ├── ValidateSchema.php ├── Replace.php ├── GenMarkdown.php ├── App.php ├── Apply.php ├── GenJson.php ├── ResolvePos.php ├── GenPhp.php ├── GenGo.php ├── GenGo │ └── BuilderOptions.php ├── Base.php └── BuildSchema.php ├── phpstan.neon ├── bin └── json-cli ├── .github └── workflows │ ├── test-unit.yml │ ├── test-unit-cov.yml │ └── cloc.yml ├── LICENSE ├── composer.json ├── knife.svg ├── CHANGELOG.md ├── README.md └── composer.lock /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:cli-alpine 2 | 3 | COPY ./json-cli /bin/json-cli 4 | 5 | WORKDIR /code -------------------------------------------------------------------------------- /src/ExitCode.php: -------------------------------------------------------------------------------- 1 | resolvers as $resolver) { 15 | $data = $resolver->getSchemaData($url); 16 | if (false !== $data) { 17 | return $data; 18 | } 19 | } 20 | 21 | return false; 22 | } 23 | } -------------------------------------------------------------------------------- /bin/json-cli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 19 | } catch (ExitCode $exception) { 20 | die($exception->getCode()); 21 | } -------------------------------------------------------------------------------- /src/Rearrange.php: -------------------------------------------------------------------------------- 1 | description = 'Rearrange json document in the order of another (original) json document'; 13 | } 14 | 15 | 16 | public function performAction() 17 | { 18 | $this->prePerform(); 19 | if (null === $this->diff) { 20 | return; 21 | } 22 | 23 | $this->out = $this->diff->getRearranged(); 24 | 25 | $this->postPerform(); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /src/SchemaResolver.php: -------------------------------------------------------------------------------- 1 | schemaData = Schema::object()->setAdditionalProperties(Schema::object()) 22 | ->setDescription('Map of schema url to schema data.'); 23 | $properties->schemaFiles = Schema::object()->setAdditionalProperties(Schema::string()) 24 | ->setDescription('Map of schema url to file path containing schema data.'); 25 | } 26 | } -------------------------------------------------------------------------------- /src/PrettyPrint.php: -------------------------------------------------------------------------------- 1 | path = Command\Option::create()->setIsUnnamed()->setIsRequired() 20 | ->setDescription('Path to .json/.yaml/.yml/.serialized file'); 21 | parent::setUpDefinition($definition, $options); 22 | $definition->description = 'Pretty print/convert document'; 23 | unset($options->pretty); 24 | } 25 | 26 | public function performAction() 27 | { 28 | $this->out = $this->readData($this->path); 29 | $this->postPerform(); 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /.github/workflows/test-unit.yml: -------------------------------------------------------------------------------- 1 | name: test-unit 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - main 7 | pull_request: 8 | jobs: 9 | run: 10 | runs-on: ${{ matrix.operating-system }} 11 | strategy: 12 | matrix: 13 | operating-system: [ 'ubuntu-latest' ] 14 | php-versions: [ '5.6', '7.0', '7.1', '7.2', '7.3', '8.0' ] 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | 19 | - name: Cache vendor 20 | uses: actions/cache@v2 21 | with: 22 | path: | 23 | vendor 24 | key: vendor-${{ hashFiles('composer.lock') }} 25 | 26 | - name: Setup PHP 27 | uses: shivammathur/setup-php@v2 28 | with: 29 | php-version: ${{ matrix.php-versions }} 30 | ini-values: post_max_size=256M, max_execution_time=180 31 | tools: composer 32 | 33 | - name: Populate vendor 34 | run: '[ -e vendor ] || composer install' 35 | 36 | - name: Run Tests 37 | run: make test -------------------------------------------------------------------------------- /src/Minify.php: -------------------------------------------------------------------------------- 1 | path = Command\Option::create()->setIsUnnamed()->setIsRequired() 20 | ->setDescription('Path to JSON/YAML file'); 21 | parent::setUpDefinition($definition, $options); 22 | unset($options->pretty); 23 | unset($options->toYaml); 24 | $options->eol = Command\Option::create()->setDescription('Add line break to the output'); 25 | $definition->description = 'Minify JSON document'; 26 | } 27 | 28 | public function performAction() 29 | { 30 | $this->out = $this->readData($this->path); 31 | $this->postPerform(); 32 | if ($this->eol) { 33 | echo "\n"; 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /.github/workflows/test-unit-cov.yml: -------------------------------------------------------------------------------- 1 | name: test-unit-cov 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - main 7 | pull_request: 8 | jobs: 9 | run: 10 | runs-on: ${{ matrix.operating-system }} 11 | strategy: 12 | matrix: 13 | operating-system: [ 'ubuntu-latest' ] 14 | php-versions: [ '7.4' ] 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | 19 | - name: Cache vendor 20 | uses: actions/cache@v2 21 | with: 22 | path: | 23 | vendor 24 | key: vendor-${{ hashFiles('composer.lock') }} 25 | 26 | - name: Setup PHP 27 | uses: shivammathur/setup-php@v2 28 | with: 29 | php-version: ${{ matrix.php-versions }} 30 | ini-values: post_max_size=256M, max_execution_time=180 31 | coverage: xdebug 32 | tools: composer 33 | 34 | - name: Populate vendor 35 | run: '[ -e vendor ] || composer install' 36 | 37 | - name: Run Tests With Coverage 38 | run: make test-coverage && bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 swaggest 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "swaggest/json-cli", 3 | "description": "JSON CLI tool (diff, rearrange, pretty print, minify, yaml convert, etc...)", 4 | "type": "tool", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Viacheslav Poturaev", 9 | "email": "vearutop@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "ext-json": "*", 14 | "swaggest/json-diff": "^3.8.3", 15 | "php-yaoi/php-yaoi": "^1", 16 | "symfony/yaml": "^3", 17 | "salsify/json-streaming-parser": "^7.0", 18 | "swaggest/json-schema": "^0.12.41", 19 | "swaggest/go-code-builder": "0.4.51", 20 | "swaggest/php-code-builder": "^0.2.41", 21 | "swaggest/code-builder": "^0.3.5", 22 | "swaggest/json-schema-maker": "^0.3.7" 23 | }, 24 | "require-dev": { 25 | "phperf/phpunit": "4.8.38" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "Swaggest\\JsonCli\\": "src/" 30 | } 31 | }, 32 | "autoload-dev": { 33 | "psr-4": { 34 | "Swaggest\\JsonCli\\Tests\\": "tests/src" 35 | } 36 | }, 37 | "config": { 38 | "platform": { 39 | "php": "5.6.0" 40 | } 41 | }, 42 | "bin": [ 43 | "bin/json-cli" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /.github/workflows/cloc.yml: -------------------------------------------------------------------------------- 1 | name: cloc 2 | on: 3 | pull_request: 4 | jobs: 5 | cloc: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout code 9 | uses: actions/checkout@v2 10 | with: 11 | path: pr 12 | - name: Checkout base code 13 | uses: actions/checkout@v2 14 | with: 15 | ref: ${{ github.event.pull_request.base.sha }} 16 | path: base 17 | - name: Count Lines Of Code 18 | id: loc 19 | run: | 20 | curl -OL https://github.com/vearutop/sccdiff/releases/download/v1.0.1/linux_amd64.tar.gz && tar xf linux_amd64.tar.gz 21 | OUTPUT=$(cd pr && ../sccdiff -basedir ../base) 22 | OUTPUT="${OUTPUT//'%'/'%25'}" 23 | OUTPUT="${OUTPUT//$'\n'/'%0A'}" 24 | OUTPUT="${OUTPUT//$'\r'/'%0D'}" 25 | echo "::set-output name=diff::$OUTPUT" 26 | 27 | - name: Comment Code Lines 28 | uses: marocchino/sticky-pull-request-comment@v2 29 | with: 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 31 | header: LOC 32 | message: | 33 | ### Lines Of Code 34 | 35 | ${{ steps.loc.outputs.diff }} 36 | -------------------------------------------------------------------------------- /src/Resolve.php: -------------------------------------------------------------------------------- 1 | path = Option::create()->setType()->setIsUnnamed() 23 | ->setDescription('Path to JSON/YAML file'); 24 | $options->pointer = Option::create()->setType()->setIsUnnamed() 25 | ->setDescription('JSON Pointer, example /key4/1/a'); 26 | } 27 | 28 | /** 29 | * @throws ExitCode 30 | */ 31 | public function performAction() 32 | { 33 | $jsonData = $this->readData($this->path); 34 | try { 35 | $this->out = JsonPointer::getByPointer($jsonData, $this->pointer); 36 | } catch (Exception $e) { 37 | $this->response->error($e->getMessage()); 38 | throw new ExitCode('', 1); 39 | } 40 | $this->postPerform(); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/Json/LoadFile.php: -------------------------------------------------------------------------------- 1 | patches = Option::create()->setType()->setIsVariadic() 23 | ->setDescription('JSON patches to apply to schema file before processing, merge patches are also supported'); 24 | 25 | } 26 | 27 | protected function loadFile() 28 | { 29 | $dataValue = Base::readJsonOrYaml($this->schema, $this->response); 30 | if (!$dataValue) { 31 | throw new ExitCode('Unable to find schema in ' . $this->schema, 1); 32 | } 33 | 34 | if (!empty($this->patches)) { 35 | foreach ($this->patches as $patchPath) { 36 | $patch = Base::readJsonOrYaml($patchPath, $this->response); 37 | if (is_array($patch)) { 38 | $jp = JsonPatch::import($patch); 39 | try { 40 | $jp->apply($dataValue); 41 | } catch (Exception $e) { 42 | throw new ExitCode($e->getMessage(), 1); 43 | } 44 | } else { 45 | JsonMergePatch::apply($dataValue, $patch); 46 | } 47 | } 48 | } 49 | 50 | return $dataValue; 51 | } 52 | } -------------------------------------------------------------------------------- /src/Diff.php: -------------------------------------------------------------------------------- 1 | description = 'Make patch from two json documents, output to STDOUT'; 21 | $options->prettyShort = Command\Option::create() 22 | ->setDescription('Pretty short format'); 23 | $options->merge = Command\Option::create() 24 | ->setDescription('Use merge patch (RFC 7386)'); 25 | } 26 | 27 | 28 | public function performAction() 29 | { 30 | $this->prePerform(); 31 | if (null === $this->diff) { 32 | return; 33 | } 34 | 35 | if ($this->merge) { 36 | $this->out = $this->diff->getMergePatch(); 37 | } else { 38 | $this->out = $this->diff->getPatch(); 39 | $outJson = $this->out->jsonSerialize(); 40 | if ($this->prettyShort && !empty($outJson)) { 41 | $out = '['; 42 | foreach ($outJson as $item) { 43 | $out .= "\n " . json_encode($item, JSON_UNESCAPED_SLASHES) . ','; 44 | } 45 | $out = substr($out, 0, -1); 46 | $out .= "\n]"; 47 | $this->response->addContent($out); 48 | return; 49 | } 50 | } 51 | 52 | $this->postPerform(); 53 | } 54 | } -------------------------------------------------------------------------------- /src/BaseDiff.php: -------------------------------------------------------------------------------- 1 | originalPath = Command\Option::create()->setIsUnnamed()->setIsRequired() 22 | ->setDescription('Path to old (original) json file'); 23 | 24 | $options->newPath = Command\Option::create()->setIsUnnamed()->setIsRequired() 25 | ->setDescription('Path to new json file'); 26 | 27 | $options->rearrangeArrays = Command\Option::create() 28 | ->setDescription('Rearrange arrays to match original'); 29 | 30 | parent::setUpDefinition($definition, $options); 31 | } 32 | 33 | /** @var JsonDiff */ 34 | protected $diff; 35 | 36 | protected function prePerform() 37 | { 38 | $original = Base::readJsonOrYaml($this->originalPath, $this->response); 39 | $new = Base::readJsonOrYaml($this->newPath, $this->response); 40 | 41 | $options = 0; 42 | if ($this->rearrangeArrays) { 43 | $options += JsonDiff::REARRANGE_ARRAYS; 44 | } 45 | try { 46 | $this->diff = new JsonDiff($original, $new, $options); 47 | } catch (Exception $e) { 48 | $this->response->error($e->getMessage()); 49 | return; 50 | } 51 | 52 | $this->out = ''; 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/GenPhp/BuilderOptions.php: -------------------------------------------------------------------------------- 1 | setters = Option::create()->setDescription('Build setters'); 29 | $options->getters = Option::create()->setDescription('Build getters'); 30 | $options->noEnumConst = Option::create() 31 | ->setDescription('Do not create constants for enum/const values'); 32 | 33 | $options->declarePropertyDefaults = Option::create() 34 | ->setDescription('Use default values to initialize properties'); 35 | 36 | $options->buildAdditionalPropertiesAccessors = Option::create() 37 | ->setDescription('Build accessors for additionalProperties'); 38 | } 39 | 40 | protected function setupBuilder(PhpBuilder $builder) 41 | { 42 | $builder->buildSetters = $this->setters; 43 | $builder->buildGetters = $this->getters; 44 | 45 | $builder->makeEnumConstants = !$this->noEnumConst; 46 | $builder->declarePropertyDefaults = $this->declarePropertyDefaults; 47 | $builder->buildAdditionalPropertyMethodsOnTrue = $this->buildAdditionalPropertiesAccessors; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/DiffInfo.php: -------------------------------------------------------------------------------- 1 | withContents = Command\Option::create()->setDescription('Add content to output'); 20 | $options->withPaths = Command\Option::create()->setDescription('Add paths to output'); 21 | $definition->description = 'Show diff info for two JSON documents'; 22 | } 23 | 24 | 25 | public function performAction() 26 | { 27 | $this->prePerform(); 28 | 29 | $this->out = array( 30 | 'addedCnt' => $this->diff->getAddedCnt(), 31 | 'modifiedCnt' => $this->diff->getAddedCnt(), 32 | 'removedCnt' => $this->diff->getRemovedCnt(), 33 | ); 34 | if ($this->withPaths) { 35 | $this->out = array_merge($this->out, array( 36 | 'addedPaths' => $this->diff->getAddedPaths(), 37 | 'modifiedPaths' => $this->diff->getModifiedPaths(), 38 | 'removedPaths' => $this->diff->getRemovedPaths(), 39 | )); 40 | } 41 | if ($this->withContents) { 42 | $this->out = array_merge($this->out, array( 43 | 'added' => $this->diff->getAdded(), 44 | 'modifiedNew' => $this->diff->getModifiedNew(), 45 | 'modifiedOriginal' => $this->diff->getModifiedOriginal(), 46 | 'removed' => $this->diff->getRemoved(), 47 | )); 48 | } 49 | $this->postPerform(); 50 | } 51 | 52 | 53 | } -------------------------------------------------------------------------------- /src/GenJSDoc.php: -------------------------------------------------------------------------------- 1 | description = 'Generate JSDoc code from JSON schema'; 21 | Base::setupGenOptions($definition, $options); 22 | } 23 | 24 | 25 | public function performAction() 26 | { 27 | try { 28 | $skipRoot = false; 29 | $baseName = null; 30 | $schema = $this->loadSchema($skipRoot, $baseName); 31 | 32 | $jb = new TypeBuilder(); 33 | $jb->trimNamePrefix = $this->defPtr; 34 | 35 | if (!$schema instanceof Schema) { 36 | $this->response->error('failed to assert Schema type, ' . get_class($schema) . ' received'); 37 | throw new ExitCode('', 1); 38 | } 39 | 40 | $jb->getTypeString($schema); 41 | 42 | if ($this->output) { 43 | if (!file_exists(dirname($this->output))) { 44 | $this->response->error('Destination directory does not exist, please create: ' . dirname($this->output)); 45 | throw new ExitCode('', 1); 46 | } 47 | file_put_contents($this->output, $jb->file); 48 | 49 | } else { 50 | echo $jb->file; 51 | } 52 | } catch (\Exception $e) { 53 | $this->response->error($e->getMessage()); 54 | throw new ExitCode('', 1); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/ValidateSchema.php: -------------------------------------------------------------------------------- 1 | data = Command\Option::create()->setIsUnnamed()->setIsRequired() 21 | ->setDescription('Path to data (JSON/YAML)'); 22 | $options->schema = Command\Option::create()->setIsUnnamed() 23 | ->setDescription('Path to schema, default JSON Schema'); 24 | } 25 | 26 | 27 | /** 28 | * @throws ExitCode 29 | * @throws \Swaggest\JsonSchema\Exception 30 | */ 31 | public function performAction() 32 | { 33 | if ($this->schema) { 34 | $schemaData = $this->readData($this->schema); 35 | try { 36 | $schema = Schema::import($schemaData); 37 | } catch (InvalidValue $e) { 38 | $this->response->error('Invalid schema'); 39 | $this->response->addContent($e->getMessage()); 40 | throw new ExitCode('', 1); 41 | } catch (\Exception $e) { 42 | $this->response->error('Failed to import schema:' . $e->getMessage()); 43 | throw new ExitCode('', 1); 44 | } 45 | } else { 46 | $schema = Schema::schema(); 47 | } 48 | 49 | $data = $this->readData($this->data); 50 | 51 | try { 52 | $schema->in($data); 53 | $this->response->success('Data is valid'); 54 | } catch (InvalidValue $exception) { 55 | $this->response->error('Data is invalid'); 56 | $this->response->addContent($exception->getMessage()); 57 | throw new ExitCode('', 1); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/Replace.php: -------------------------------------------------------------------------------- 1 | path = Command\Option::create()->setIsUnnamed()->setIsRequired() 24 | ->setDescription('Path to JSON/YAML file'); 25 | $options->search = Command\Option::create()->setIsUnnamed()->setIsRequired() 26 | ->setDescription('Search JSON value'); 27 | $options->replace = Command\Option::create()->setIsUnnamed()->setIsRequired() 28 | ->setDescription('Replace JSON value'); 29 | $options->pathFilter = Command\Option::create()->setType() 30 | ->setDescription('JSON path filter regex, example "/definitions/.*/properties/deletedAt"'); 31 | $definition->description = 'Minify JSON document'; 32 | } 33 | 34 | public function performAction() 35 | { 36 | $jsonData = $this->readData($this->path); 37 | 38 | $search = json_decode($this->search); 39 | if (json_last_error()) { 40 | $this->response->error('Invalid JSON: ' . $this->search); 41 | return; 42 | } 43 | $replace = json_decode($this->replace); 44 | if (json_last_error()) { 45 | $this->response->error('Invalid JSON: ' . $this->replace); 46 | return; 47 | } 48 | 49 | $pathFilter = null; 50 | if ($this->pathFilter) { 51 | $pathFilter = '|' . $this->pathFilter . '|'; 52 | } 53 | 54 | $replacer = new JsonValueReplace($search, $replace, $pathFilter); 55 | $this->out = $replacer->process($jsonData); 56 | $this->postPerform(); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/GenMarkdown.php: -------------------------------------------------------------------------------- 1 | description = 'Generate Markdown document from JSON schema'; 21 | Base::setupGenOptions($definition, $options); 22 | } 23 | 24 | 25 | public function performAction() 26 | { 27 | try { 28 | $skipRoot = false; 29 | $baseName = null; 30 | $schema = $this->loadSchema($skipRoot, $baseName); 31 | 32 | $jb = new TypeBuilder(); 33 | $jb->trimNamePrefix = $this->defPtr; 34 | 35 | if (!$schema instanceof Schema) { 36 | $this->response->error('failed to assert Schema type, ' . get_class($schema) . ' received'); 37 | throw new ExitCode('', 1); 38 | } 39 | 40 | $jb->getTypeString($schema); 41 | 42 | $jb->sortTypes(); 43 | $out = $jb->tableOfContents(); 44 | foreach ($jb->types as $typeName => $doc) { 45 | $out .= $doc; 46 | } 47 | 48 | if ($this->output) { 49 | if (!file_exists(dirname($this->output))) { 50 | $this->response->error('Destination directory does not exist, please create: ' . dirname($this->output)); 51 | throw new ExitCode('', 1); 52 | } 53 | file_put_contents($this->output, $out); 54 | 55 | } else { 56 | echo $out; 57 | } 58 | } catch (\Exception $e) { 59 | $this->response->error($e->getMessage()); 60 | throw new ExitCode('', 1); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/App.php: -------------------------------------------------------------------------------- 1 | name = 'json-cli'; 36 | $definition->version = self::$ver; 37 | $definition->description = 'JSON CLI tool, https://github.com/swaggest/json-cli'; 38 | 39 | $commandDefinitions->diff = Diff::definition(); 40 | $commandDefinitions->apply = Apply::definition(); 41 | $commandDefinitions->rearrange = Rearrange::definition(); 42 | $commandDefinitions->diffInfo = DiffInfo::definition(); 43 | $commandDefinitions->prettyPrint = PrettyPrint::definition(); 44 | $commandDefinitions->minify = Minify::definition(); 45 | $commandDefinitions->replace = Replace::definition(); 46 | $commandDefinitions->resolve = Resolve::definition(); 47 | $commandDefinitions->resolvePos = ResolvePos::definition(); 48 | $commandDefinitions->validateSchema = ValidateSchema::definition(); 49 | $commandDefinitions->genGo = GenGo::definition(); 50 | $commandDefinitions->genPhp = GenPhp::definition(); 51 | $commandDefinitions->genJSDoc = GenJSDoc::definition(); 52 | $commandDefinitions->genJson = GenJson::definition(); 53 | $commandDefinitions->genMarkdown = GenMarkdown::definition(); 54 | $commandDefinitions->buildSchema = BuildSchema::definition(); 55 | } 56 | } -------------------------------------------------------------------------------- /src/Apply.php: -------------------------------------------------------------------------------- 1 | patchPath = Command\Option::create()->setType()->setIsUnnamed() 29 | ->setDescription('Path to JSON patch file'); 30 | $options->basePath = Command\Option::create()->setType()->setIsUnnamed() 31 | ->setDescription('Path to JSON base file'); 32 | 33 | parent::setUpDefinition($definition, $options); 34 | 35 | $definition->description = 'Apply patch to base json document, output to STDOUT'; 36 | $options->tolerateErrors = Command\Option::create() 37 | ->setDescription('Continue on error'); 38 | $options->merge = Command\Option::create() 39 | ->setDescription('Use merge patch (RFC 7386)'); 40 | } 41 | 42 | /** 43 | * @throws ExitCode 44 | */ 45 | public function performAction() 46 | { 47 | $patchJson = $this->readData($this->patchPath); 48 | $base = $this->readData($this->basePath); 49 | 50 | try { 51 | if ($this->merge) { 52 | JsonMergePatch::apply($base, $patchJson); 53 | $this->out = $base; 54 | } else { 55 | $patch = JsonPatch::import($patchJson); 56 | $errors = $patch->apply($base, !$this->tolerateErrors); 57 | foreach ($errors as $error) { 58 | $this->response->error($error->getMessage()); 59 | } 60 | $this->out = $base; 61 | } 62 | } catch (Exception $e) { 63 | $this->response->error($e->getMessage()); 64 | throw new ExitCode('', 1); 65 | } 66 | 67 | $this->postPerform(); 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /src/GenJson.php: -------------------------------------------------------------------------------- 1 | description = 'Generate JSON sample from JSON schema'; 26 | Base::setupGenOptions($definition, $options); 27 | $options->maxNesting = Command\Option::create()->setType() 28 | ->setDescription('Max nesting level, default 10'); 29 | $options->defaultAdditionalProperties = Command\Option::create() 30 | ->setDescription('Treat non-existent `additionalProperties` as `additionalProperties: true`'); 31 | $options->randSeed = Command\Option::create()->setType() 32 | ->setDescription('Integer random seed for deterministic output'); 33 | Base::setUpDefinition($definition, $options); 34 | Base::setupLoadFileOptions($options); 35 | } 36 | 37 | public function performAction() 38 | { 39 | if ($this->randSeed !== null) { 40 | mt_srand((int)$this->randSeed); 41 | } 42 | 43 | try { 44 | $skipRoot = false; 45 | $baseName = null; 46 | $schema = $this->loadSchema($skipRoot, $baseName); 47 | 48 | if (!$schema instanceof Schema) { 49 | $this->response->error('failed to assert Schema type, ' . get_class($schema) . ' received'); 50 | throw new ExitCode('', 1); 51 | } 52 | 53 | $options = new Options; 54 | $options->maxNesting = $this->maxNesting; 55 | $options->defaultAdditionalProperties = $this->defaultAdditionalProperties; 56 | $instanceFaker = new InstanceFaker($schema, $options); 57 | 58 | $this->out = $instanceFaker->makeValue(); 59 | 60 | $this->postPerform(); 61 | } catch (\Exception $e) { 62 | $this->response->error($e->getMessage()); 63 | throw new ExitCode('', 1); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /src/ResolvePos.php: -------------------------------------------------------------------------------- 1 | path = Command\Option::create()->setType()->setIsUnnamed() 26 | ->setDescription('Path to JSON file'); 27 | $options->pointer = Command\Option::create()->setType()->setIsUnnamed() 28 | ->setDescription('JSON Pointer, example /key4/1/a'); 29 | $options->dumpAll = Command\Option::create()->setDescription('Dump all pointer positions from JSON'); 30 | } 31 | 32 | /** 33 | * @throws ExitCode 34 | */ 35 | public function performAction() 36 | { 37 | $listener = new FilePosition\PositionResolver(); 38 | $stream = fopen($this->path, 'r'); 39 | if ($stream === false) { 40 | $this->response->error('Failed to open ' . $this->path); 41 | die(1); 42 | } 43 | try { 44 | if ($stream !== false) { 45 | $parser = new Parser($stream, $listener); 46 | $parser->parse(); 47 | fclose($stream); 48 | } 49 | } catch (\Exception $e) { 50 | fclose($stream); 51 | $this->response->error($e->getMessage()); 52 | throw new ExitCode('', 1); 53 | } 54 | 55 | if ($this->dumpAll) { 56 | $rows = array(); 57 | foreach ($listener->resolved as $pointer => $pos) { 58 | $rows[] = array( 59 | 'Pos' => $pos, 60 | 'Ptr' => $pointer, 61 | ); 62 | } 63 | $this->response->addContent(new Rows(new \ArrayIterator($rows))); 64 | } else { 65 | try { 66 | // Convert to non-URI pointer 67 | $pointer = JsonPointer::buildPath(JsonPointer::splitPath($this->pointer)); 68 | } catch (Exception $e) { 69 | $this->response->error($e->getMessage()); 70 | throw new ExitCode('', 1); 71 | } 72 | 73 | if (isset($listener->resolved[$pointer])) { 74 | $this->response->addContent($listener->resolved[$pointer]); 75 | } else { 76 | $this->response->error('Pointer not found'); 77 | throw new ExitCode('', 1); 78 | } 79 | } 80 | 81 | 82 | } 83 | 84 | 85 | } -------------------------------------------------------------------------------- /knife.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 9 | 11 | 13 | 17 | 20 | 23 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/FilePosition/PositionResolver.php: -------------------------------------------------------------------------------- 1 | pathState = new PathState(); 18 | $this->pathState->path = ''; 19 | } 20 | 21 | public function startDocument() 22 | { 23 | } 24 | 25 | public function endDocument() 26 | { 27 | } 28 | 29 | public function startObject() 30 | { 31 | $path = $this->pathState->path; 32 | if ($this->pathState->isArray) { 33 | $index = $this->pathState->arrayIndex++; 34 | $path = $this->pathState->path . '/' . $index; 35 | $this->resolved[$path] = $this->currentLine . ':' . $this->currentChar; 36 | } 37 | 38 | $this->stack[] = $this->pathState; 39 | $pathState = new PathState(); 40 | $pathState->path = $path; 41 | $this->pathState = $pathState; 42 | } 43 | 44 | public function endObject() 45 | { 46 | $this->pathState = array_pop($this->stack); 47 | if ($this->pathState->isKey) { 48 | $this->pathState = array_pop($this->stack); 49 | } 50 | } 51 | 52 | 53 | public function startArray() 54 | { 55 | $path = $this->pathState->path; 56 | if ($this->pathState->isArray) { 57 | $index = $this->pathState->arrayIndex++; 58 | $path = $this->pathState->path . '/' . $index; 59 | $this->resolved[$path] = $this->currentLine . ':' . $this->currentChar; 60 | } 61 | 62 | $this->stack[] = $this->pathState; 63 | $pathState = new PathState(); 64 | $pathState->path = $path; 65 | $pathState->isArray = true; 66 | $this->pathState = $pathState; 67 | } 68 | 69 | public function endArray() 70 | { 71 | $this->pathState = array_pop($this->stack); 72 | if ($this->pathState->isKey) { 73 | $this->pathState = array_pop($this->stack); 74 | } 75 | } 76 | 77 | public function key($key) 78 | { 79 | $path = $this->pathState->path . '/' . JsonPointer::escapeSegment($key); 80 | 81 | $this->stack[] = $this->pathState; 82 | $pathState = new PathState(); 83 | $pathState->path = $path; 84 | $pathState->isKey = true; 85 | $this->pathState = $pathState; 86 | 87 | 88 | $this->resolved[$path] = $this->currentLine . ':' . $this->currentChar; 89 | } 90 | 91 | public function value($value) 92 | { 93 | if ($this->pathState->isArray) { 94 | $index = $this->pathState->arrayIndex++; 95 | $itemPath = $this->pathState->path . '/' . $index; 96 | $this->resolved[$itemPath] = $this->currentLine . ':' . $this->currentChar; 97 | } elseif ($this->pathState->isKey) { 98 | $this->pathState = array_pop($this->stack); 99 | } 100 | } 101 | 102 | public function whitespace($whitespace) 103 | { 104 | } 105 | 106 | private $currentLine; 107 | private $currentChar; 108 | 109 | /** 110 | * @param int $line 111 | * @param int $char 112 | */ 113 | public function filePosition($line, $char) 114 | { 115 | $this->currentLine = $line; 116 | $this->currentChar = $char; 117 | } 118 | 119 | 120 | } -------------------------------------------------------------------------------- /src/GenPhp.php: -------------------------------------------------------------------------------- 1 | description = 'Generate PHP code from JSON schema'; 32 | Base::setupGenOptions($definition, $options); 33 | 34 | $options->ns = Command\Option::create() 35 | ->setDescription('Namespace to use for generated classes, example \MyClasses')->setType()->setIsRequired(); 36 | 37 | $options->nsPath = Command\Option::create() 38 | ->setDescription('Path to store generated classes, example ./src/MyClasses') 39 | ->setType() 40 | ->setIsRequired(); 41 | 42 | $options->rootName = Command\Option::create()->setType() 43 | ->setDescription('Root class name, default "Structure", only used for # pointer'); 44 | 45 | static::setupBuilderOptions($options); 46 | Base::setupGenOptions($definition, $options); 47 | } 48 | 49 | 50 | public function performAction() 51 | { 52 | try { 53 | $skipRoot = false; 54 | $baseName = null; 55 | $schema = $this->loadSchema($skipRoot, $baseName); 56 | 57 | $appPath = realpath($this->nsPath); 58 | if (!$appPath) { 59 | $this->response->error('Could not find directory ' . $this->nsPath); 60 | throw new ExitCode('', 1); 61 | } 62 | $appNs = $this->ns; 63 | 64 | $app = new PhpApp(); 65 | $app->setNamespaceRoot($appNs, '.'); 66 | 67 | $builder = new PhpBuilder(); 68 | $this->setupBuilder($builder); 69 | 70 | $builder->classCreatedHook = new ClassHookCallback(function (PhpClass $class, $path, $schema) 71 | use ($app, $appNs, $skipRoot, $baseName) { 72 | if ($skipRoot && '#' === $path) { 73 | return; 74 | } 75 | 76 | $desc = ''; 77 | if ($schema->title) { 78 | $desc = $schema->title; 79 | } 80 | if ($schema->description) { 81 | $desc .= "\n" . $schema->description; 82 | } 83 | if ($fromRefs = $schema->getFromRefs()) { 84 | $desc .= "\nBuilt from " . implode("\n" . ' <- ', $fromRefs); 85 | } 86 | $class->setDescription(trim($desc)); 87 | 88 | $class->setNamespace($appNs); 89 | if ('#' === $path) { 90 | $class->setName($this->rootName); 91 | } else { 92 | if (!empty($fromRefs)) { 93 | $path = $fromRefs[0]; 94 | } 95 | foreach ($this->defPtr as $defPtr) { 96 | if (isset($baseName)) { 97 | $baseNameDefPtr = $baseName . $defPtr; 98 | if ($baseNameDefPtr === substr($path, 0, strlen($baseNameDefPtr))) { 99 | $path = substr($path, strlen($baseNameDefPtr)); 100 | $className = PhpCode::makePhpClassName($path); 101 | $class->setName($className); 102 | } 103 | } 104 | 105 | if ($defPtr === substr($path, 0, strlen($defPtr))) { 106 | $className = PhpCode::makePhpClassName(substr($path, strlen($defPtr))); 107 | $class->setName($className); 108 | } 109 | } 110 | } 111 | $app->addClass($class); 112 | }); 113 | 114 | if (!$schema instanceof Schema) { 115 | $this->response->error('failed to assert Schema type, ' . get_class($schema) . ' received'); 116 | throw new ExitCode('', 1); 117 | } 118 | $builder->getType($schema); 119 | $app->store($appPath); 120 | $this->response->success("Classes are generated in " . $appPath); 121 | } catch (\Exception $e) { 122 | $this->response->error($e->getMessage()); 123 | throw new ExitCode('', 1); 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /src/GenGo.php: -------------------------------------------------------------------------------- 1 | description = 'Generate Go code from JSON schema'; 41 | Base::setupGenOptions($definition, $options); 42 | 43 | $options->output = Command\Option::create() 44 | ->setDescription('Path to output .go file, STDOUT is used by default')->setType(); 45 | 46 | $options->packageName = Command\Option::create()->setType() 47 | ->setDescription('Go package name, default "entities"'); 48 | 49 | $options->rootName = Command\Option::create()->setType() 50 | ->setDescription('Go root struct name, default "Structure", only used for # pointer'); 51 | 52 | $options->withTests = Command\Option::create() 53 | ->setDescription('Generate (un)marshaling tests for entities (experimental feature)'); 54 | 55 | static::setUpBuilderOptions($options); 56 | } 57 | 58 | 59 | public function performAction() 60 | { 61 | try { 62 | $skipRoot = false; 63 | $baseName = null; 64 | $schema = $this->loadSchema($skipRoot, $baseName); 65 | 66 | $builderOptions = $this->makeGoBuilderOptions(); 67 | $builder = new GoBuilder(); 68 | $builder->options = $builderOptions; 69 | 70 | $pathToNameHook = new StripPrefixPathToNameHook(); 71 | 72 | if (!empty($this->defPtr)) { 73 | $pathToNameHook->prefixes = []; 74 | foreach ($this->defPtr as $defPtr) { 75 | if (isset($baseName)) { 76 | $pathToNameHook->prefixes[] = $baseName . $defPtr; 77 | } 78 | $pathToNameHook->prefixes[] = $defPtr; 79 | } 80 | } 81 | 82 | if (isset($baseName)) { 83 | $pathToNameHook->prefixes[] = $baseName; 84 | } 85 | 86 | $builder->pathToNameHook = $pathToNameHook; 87 | 88 | $builder->structCreatedHook = new StructHookCallback(function (StructDef $structDef, $path, $schema) { 89 | if ('#' === $path) { 90 | $structDef->setName($this->rootName); 91 | } 92 | }); 93 | if ($schema instanceof Schema) { 94 | $builder->getType($schema); 95 | } 96 | 97 | $goFile = new GoFile($this->packageName); 98 | $goFile->fileComment = 'Code generated by github.com/swaggest/json-cli ' . App::$ver . ', DO NOT EDIT.'; 99 | $goFile->setComment('Package ' . $this->packageName . ' contains JSON mapping structures.'); 100 | 101 | $goTestFile = new GoFile($this->packageName . '_test'); 102 | $goTestFile->setPackage($this->packageName); 103 | $goTestFile->fileComment = 'Code generated by github.com/swaggest/json-cli ' . App::$ver . ', DO NOT EDIT.'; 104 | 105 | mt_srand(1); 106 | 107 | foreach ($builder->getGeneratedStructs() as $generatedStruct) { 108 | if ($skipRoot && $generatedStruct->path === '#') { 109 | continue; 110 | } 111 | $goFile->getCode()->addSnippet($generatedStruct->structDef); 112 | if ($this->withTests) { 113 | $goTestFile->getCode()->addSnippet(MarshalingTestFunc::make($generatedStruct, $builder->options)); 114 | } 115 | } 116 | $goFile->getCode()->addSnippet($builder->getCode()); 117 | 118 | if ($this->output) { 119 | if (!file_exists(dirname($this->output))) { 120 | $this->response->error('Destination directory does not exist, please create: ' . dirname($this->output)); 121 | throw new ExitCode('', 1); 122 | } 123 | file_put_contents($this->output, $goFile->render()); 124 | 125 | if ($this->withTests) { 126 | file_put_contents(str_replace('.go', '_test.go', $this->output), $goTestFile->render()); 127 | } 128 | } else { 129 | echo $goFile->render(); 130 | } 131 | } catch (\Exception $e) { 132 | $this->response->error($e->getMessage()); 133 | throw new ExitCode('', 1); 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /src/GenGo/BuilderOptions.php: -------------------------------------------------------------------------------- 1 | */ 32 | public $renames = []; 33 | 34 | /** @var bool */ 35 | public $requireXGenerate = false; 36 | 37 | /** @var bool */ 38 | public $validateRequired = false; 39 | 40 | /** @var string[] */ 41 | public $nameTags = []; 42 | 43 | /** @var string */ 44 | public $config; 45 | 46 | /** 47 | * @param \stdClass|static $options 48 | */ 49 | public static function setUpBuilderOptions($options) 50 | { 51 | $options->showConstProperties = Option::create() 52 | ->setDescription('Show properties with constant values, hidden by default'); 53 | 54 | $options->keepParentInPropertyNames = Option::create() 55 | ->setDescription('Keep parent prefix in property name, removed by default'); 56 | 57 | $options->ignoreNullable = Option::create() 58 | ->setDescription('Add `omitempty` to nullable properties, removed by default'); 59 | 60 | $options->ignoreXGoType = Option::create() 61 | ->setName('ignore-x-go-type') 62 | ->setDescription('Ignore `x-go-type` in schema to skip generation'); 63 | 64 | $options->withZeroValues = Option::create() 65 | ->setDescription('Use pointer types to avoid zero value ambiguity'); 66 | 67 | $options->enableXNullable = Option::create() 68 | ->setDescription('Add `null` to types if `x-nullable` or `nullable` is available'); 69 | 70 | $options->enableDefaultAdditionalProperties = Option::create() 71 | ->setDescription('Add field property for undefined `additionalProperties`'); 72 | 73 | $options->fluentSetters = Option::create() 74 | ->setDescription('Add fluent setters to struct fields'); 75 | 76 | $options->ignoreRequired = Option::create() 77 | ->setDescription('Ignore if property is required when deciding on pointer type or omitempty'); 78 | 79 | $options->renames = Option::create()->setIsVariadic()->setType() 80 | ->setDescription('Map of exported symbol renames, example From:To'); 81 | 82 | $options->requireXGenerate = Option::create() 83 | ->setDescription('Generate properties with `x-generate: true` only'); 84 | 85 | $options->validateRequired = Option::create() 86 | ->setDescription('Generate validation code to check required properties during unmarshal'); 87 | 88 | $options->nameTags = Option::create()->setIsVariadic()->setType() 89 | ->setDescription('Set additional field tags with property name, example "msgp bson"'); 90 | 91 | $options->config = Option::create()->setType() 92 | ->setDescription('Path to config JSON file to load options from. Schema:'); 93 | 94 | $tb = new TypeBuilder(); 95 | $tb->getTypeString(Options::schema()->exportSchema()); 96 | $options->config->description .= "\n" . trim(substr($tb->file, 97)); // Stripping header. 97 | } 98 | 99 | /** 100 | * @return Options 101 | * @throws ExitCode 102 | */ 103 | protected function makeGoBuilderOptions() 104 | { 105 | $options = new Options(); 106 | if (!empty($this->config)) { 107 | $data = file_get_contents($this->config); 108 | if (empty($data)) { 109 | throw new ExitCode("empty or missing config file", 1); 110 | } 111 | $json = json_decode($data); 112 | if (empty($json)) { 113 | throw new ExitCode("invalid json in config file", 1); 114 | } 115 | 116 | $options = Options::import($json); 117 | } 118 | 119 | $options = $options->jsonSerialize(); 120 | 121 | $options->hideConstProperties = !$this->showConstProperties; 122 | $options->trimParentFromPropertyNames = !$this->keepParentInPropertyNames; 123 | $options->ignoreNullable = $this->ignoreNullable; 124 | $options->ignoreXGoType = $this->ignoreXGoType; 125 | $options->withZeroValues = $this->withZeroValues; 126 | $options->enableXNullable = $this->enableXNullable; 127 | $options->defaultAdditionalProperties = $this->enableDefaultAdditionalProperties; 128 | $options->fluentSetters = $this->fluentSetters; 129 | $options->ignoreRequired = $this->ignoreRequired; 130 | $options->requireXGenerate = $this->requireXGenerate; 131 | $options->validateRequired = $this->validateRequired; 132 | $options->nameTags = $this->nameTags; 133 | if (!empty($this->renames)) { 134 | foreach ($this->renames as $rename) { 135 | $rename = explode(':', $rename, 2); 136 | $options->renames[$rename[0]] = $rename[1]; 137 | } 138 | } 139 | 140 | return $options; 141 | } 142 | 143 | } -------------------------------------------------------------------------------- /src/Base.php: -------------------------------------------------------------------------------- 1 | pretty = Command\Option::create() 34 | ->setDescription('Pretty-print result JSON'); 35 | $options->output = Command\Option::create()->setType() 36 | ->setDescription('Path to output result, default STDOUT'); 37 | $options->schemaResolver = Command\Option::create()->setType() 38 | ->setDescription('Path to schema resolver JSON file. Schema:'); 39 | $tb = new TypeBuilder(); 40 | $tb->getTypeString(SchemaResolver::schema()->exportSchema()); 41 | $options->schemaResolver->description .= "\n" . trim(substr($tb->file, 77)); // Stripping header. 42 | 43 | 44 | $options->toYaml = Command\Option::create()->setDescription('Output in YAML format'); 45 | $options->toSerialized = Command\Option::create()->setDescription('Output in PHP serialized format'); 46 | } 47 | 48 | 49 | protected $out; 50 | 51 | /** 52 | * @param string $path 53 | * @return mixed 54 | * @throws ExitCode 55 | */ 56 | protected function readData($path) 57 | { 58 | return self::readJsonOrYaml($path, $this->response); 59 | } 60 | 61 | /** 62 | * @param string $path 63 | * @param Response $response 64 | * @return mixed 65 | * @throws ExitCode 66 | */ 67 | public static function readJsonOrYaml($path, $response) 68 | { 69 | $fileData = file_get_contents($path); 70 | if (!$fileData) { 71 | $response->error('Unable to read ' . $path); 72 | throw new ExitCode('', 1); 73 | } 74 | if (substr($path, -5) === '.yaml' || substr($path, -4) === '.yml') { 75 | $jsonData = Yaml::parse($fileData, Yaml::PARSE_OBJECT + Yaml::PARSE_OBJECT_FOR_MAP); 76 | } elseif (substr($path, -11) === '.serialized') { 77 | $jsonData = unserialize($fileData); 78 | } else { 79 | $jsonData = json_decode($fileData); 80 | } 81 | 82 | return $jsonData; 83 | } 84 | 85 | 86 | protected function postPerform() 87 | { 88 | $options = JSON_UNESCAPED_SLASHES + JSON_UNESCAPED_UNICODE; 89 | if ($this->pretty) { 90 | $options += JSON_PRETTY_PRINT; 91 | } 92 | 93 | if ($this->toYaml) { 94 | $result = Yaml::dump($this->out, 2, 2, Yaml::DUMP_OBJECT_AS_MAP); 95 | } elseif ($this->toSerialized) { 96 | $result = serialize($this->out); 97 | } else { 98 | $result = json_encode($this->out, $options); 99 | } 100 | 101 | if ($this->output) { 102 | file_put_contents($this->output, $result); 103 | } else { 104 | echo $result, "\n"; 105 | } 106 | } 107 | 108 | 109 | /** @var string */ 110 | public $schema; 111 | /** @var string[] */ 112 | public $defPtr = ['#/definitions']; 113 | /** @var string[] */ 114 | public $ptrInSchema; 115 | 116 | /** 117 | * @param Command\Definition $definition 118 | * @param static|mixed $options 119 | */ 120 | protected static function setupGenOptions(Command\Definition $definition, $options) 121 | { 122 | $options->schema = Command\Option::create() 123 | ->setDescription('Path to JSON schema file, use `-` for STDIN')->setIsUnnamed()->setIsRequired(); 124 | 125 | $options->ptrInSchema = Command\Option::create()->setType()->setIsVariadic() 126 | ->setDescription('JSON pointers to structure in root schema, default #'); 127 | 128 | $options->defPtr = Command\Option::create()->setType()->setIsVariadic() 129 | ->setDescription('Definitions pointers to strip from symbol names, default #/definitions'); 130 | 131 | $options->schemaResolver = Command\Option::create()->setType() 132 | ->setDescription('Path to schema resolver JSON file. Schema:'); 133 | $tb = new TypeBuilder(); 134 | $tb->getTypeString(SchemaResolver::schema()->exportSchema()); 135 | $options->schemaResolver->description .= "\n" . trim(substr($tb->file, 77)); // Stripping header. 136 | 137 | static::setupLoadFileOptions($options); 138 | } 139 | 140 | /** 141 | * @param bool $skipRoot 142 | * @param string $baseName 143 | * @return \Swaggest\JsonSchema\SchemaContract 144 | * @throws Exception 145 | * @throws ExitCode 146 | * @throws \Swaggest\JsonSchema\Exception 147 | * @throws \Swaggest\JsonSchema\InvalidValue 148 | */ 149 | protected function loadSchema(&$skipRoot, &$baseName) 150 | { 151 | if ($this->schema === '-') { 152 | $this->schema = 'php://stdin'; 153 | } 154 | 155 | $resolver = new ResolverMux(); 156 | $preloaded = new Preloaded(); 157 | 158 | if ($this->schemaResolver !== null) { 159 | $data = file_get_contents($this->schemaResolver); 160 | if (empty($data)) { 161 | throw new ExitCode("empty or missing schema resolver file", 1); 162 | } 163 | $json = json_decode($data); 164 | if (empty($json)) { 165 | throw new ExitCode("invalid json in schema resolver file", 1); 166 | } 167 | 168 | $schemaResolver = SchemaResolver::import($json); 169 | 170 | foreach ($schemaResolver->schemaData as $url => $data) { 171 | $preloaded->setSchemaData($url, $data); 172 | } 173 | 174 | foreach ($schemaResolver->schemaFiles as $url => $file) { 175 | $preloaded->setSchemaFile($url, $file); 176 | } 177 | } 178 | 179 | $resolver->resolvers[] = $preloaded; 180 | 181 | $dataValue = $this->loadFile(); 182 | $data = $dataValue; 183 | 184 | if (!empty($this->ptrInSchema)) { 185 | $baseName = basename($this->schema); 186 | $skipRoot = true; 187 | $preloaded->setSchemaData($baseName, $dataValue); 188 | $data = new \stdClass(); 189 | 190 | foreach ($this->defPtr as $defPtr) { 191 | $this->defPtr[] = $baseName . $defPtr; 192 | } 193 | $this->defPtr[] = $baseName; 194 | 195 | foreach ($this->ptrInSchema as $i => $ptr) { 196 | $data->oneOf[$i] = (object)[Schema::PROP_REF => $baseName . $ptr]; 197 | } 198 | } 199 | 200 | $resolver->resolvers[] = new BasicFetcher(); 201 | return Schema::import($data, new Context($resolver)); 202 | } 203 | } -------------------------------------------------------------------------------- /src/BuildSchema.php: -------------------------------------------------------------------------------- 1 | data = Command\Option::create()->setIsUnnamed()->setIsRequired() 49 | ->setDescription('Path to data (JSON/YAML)'); 50 | $options->schema = Command\Option::create()->setIsUnnamed() 51 | ->setDescription('Path to parent schema'); 52 | $options->ptrInSchema = Command\Option::create()->setType() 53 | ->setDescription('JSON pointer to structure in root schema, default #'); 54 | $options->ptrInData = Command\Option::create()->setType() 55 | ->setDescription('JSON pointer to structure in data, default #'); 56 | $options->jsonl = Command\Option::create()->setDescription('Data is a stream of JSON Lines'); 57 | 58 | $options->useNullable = Command\Option::create() 59 | ->setDescription('Use `nullable: true` instead of `type: null`, OAS 3.0 compatibility'); 60 | 61 | $options->useXNullable = Command\Option::create() 62 | ->setDescription('Use `x-nullable: true` instead of `type: null`, Swagger 2.0 compatibility'); 63 | 64 | $options->defsPtr = Command\Option::create()->setType() 65 | ->setDescription('Location to put new definitions. default: "#/definitions/"'); 66 | 67 | $options->collectExamples = Command\Option::create() 68 | ->setDescription('Collect scalar values example'); 69 | 70 | $options->heuristicRequired = Command\Option::create() 71 | ->setDescription('Mark properties that are available in all samples as `required`.'); 72 | 73 | $options->additionalData = Command\Option::create()->setType()->setIsVariadic() 74 | ->setDescription('Additional paths to data'); 75 | 76 | parent::setUpDefinition($definition, $options); 77 | } 78 | 79 | 80 | /** 81 | * @throws ExitCode 82 | * @throws \Swaggest\JsonSchema\Exception 83 | */ 84 | public function performAction() 85 | { 86 | $schema = new Schema(); 87 | 88 | if ($this->schema) { 89 | $schemaDataOrig = $this->readData($this->schema); 90 | $schemaData = $schemaDataOrig; 91 | 92 | $resolver = new ResolverMux(); 93 | 94 | if (!empty($this->ptrInSchema)) { 95 | $baseName = basename($this->schema); 96 | $preloaded = new Preloaded(); 97 | $preloaded->setSchemaData($baseName, $schemaData); 98 | $resolver->resolvers[] = $preloaded; 99 | $schemaData = (object)[Schema::PROP_REF => $baseName . $this->ptrInSchema]; 100 | } 101 | 102 | $resolver->resolvers[] = new BasicFetcher(); 103 | 104 | try { 105 | $schemaContract = Schema::import($schemaData, new Context($resolver)); 106 | if ($schemaContract instanceof Schema) { 107 | $schema = $schemaContract; 108 | } 109 | } catch (InvalidValue $e) { 110 | $this->response->error('Invalid schema'); 111 | $this->response->addContent($e->getMessage()); 112 | throw new ExitCode('', 1); 113 | } catch (\Exception $e) { 114 | $this->response->error('Failed to import schema:' . $e->getMessage()); 115 | throw new ExitCode('', 1); 116 | } 117 | } 118 | 119 | $maker = new SchemaMaker($schema); 120 | $maker->options->useXNullable = $this->useXNullable; 121 | $maker->options->useNullable = $this->useNullable; 122 | $maker->options->defsPtr = $this->defsPtr; 123 | $maker->options->collectExamples = $this->collectExamples; 124 | $maker->options->heuristicRequired = $this->heuristicRequired; 125 | 126 | if ($this->jsonl) { 127 | $pathInData = []; 128 | if ($this->ptrInData) { 129 | $pathInData = JsonPointer::splitPath($this->ptrInData); 130 | } 131 | 132 | $handle = fopen($this->data, "r"); 133 | if ($handle) { 134 | while (($buffer = fgets($handle)) !== false) { 135 | $item = json_decode($buffer); 136 | // Tolerate and skip malformed JSON line. 137 | if (null === $item) { 138 | continue; 139 | } 140 | if ($this->ptrInData) { 141 | $item = JsonPointer::get($item, $pathInData); 142 | } 143 | $maker->addInstanceValue($item); 144 | } 145 | if (!feof($handle)) { 146 | echo "Error: unexpected fgets() fail\n"; 147 | } 148 | fclose($handle); 149 | } 150 | } else { 151 | $data = $this->readData($this->data); 152 | $maker->addInstanceValue($data); 153 | 154 | if (!empty($this->additionalData)) { 155 | foreach ($this->additionalData as $path) { 156 | $data = $this->readData($path); 157 | $maker->addInstanceValue($data); 158 | } 159 | } 160 | } 161 | 162 | 163 | $s = Schema::export($schema); 164 | $this->out = $s; 165 | 166 | if ($this->ptrInSchema && isset($schemaDataOrig)) { 167 | $tmp = json_encode($schemaDataOrig); 168 | if ($tmp === false) { 169 | throw new ExitCode('Failed to encode JSON', 1); 170 | } 171 | $schemaDataResult = json_decode($tmp); 172 | 173 | $defs = JsonPointer::get($s, JsonPointer::splitPath(rtrim($this->defsPtr, '/'))); 174 | foreach ($defs as $name => $def) { 175 | JsonPointer::add($schemaDataResult, JsonPointer::splitPath($this->defsPtr . $name), $def); 176 | } 177 | JsonPointer::remove($s, JsonPointer::splitPath(rtrim($this->defsPtr, '/'))); 178 | JsonPointer::add($schemaDataResult, JsonPointer::splitPath($this->ptrInSchema), $s); 179 | 180 | $tmp = json_encode($schemaDataResult); 181 | if ($tmp === false) { 182 | throw new ExitCode('Failed to encode JSON', 1); 183 | } 184 | $schemaDataResult = json_decode($tmp); 185 | $diff = new JsonDiff($schemaDataOrig, $schemaDataResult, JsonDiff::REARRANGE_ARRAYS); 186 | $this->out = $diff->getRearranged(); 187 | } 188 | 189 | $this->postPerform(); 190 | } 191 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [1.11.2] - 2023-12-19 8 | 9 | ### Added 10 | - Dependencies updated. 11 | 12 | ## [1.11.1] - 2022-11-14 13 | 14 | ### Fixed 15 | - Handling of `*Of` in PHP generation. 16 | 17 | ## [1.11.0] - 2022-09-18 18 | 19 | ### Added 20 | - Configurable schema url resolver 21 | 22 | ## [1.10.0] - 2022-09-16 23 | 24 | ### Added 25 | - Dependencies updated. 26 | - Generate Markdown from JSON Schema. 27 | - Options for Go generator with JSON file. 28 | 29 | ## [1.9.1] - 2022-04-21 30 | 31 | ### Added 32 | - Dependencies updated. 33 | 34 | ### Fixed 35 | - Compatibility with PHP 8.1. 36 | 37 | ## [1.9.0] - 2021-10-28 38 | 39 | ### Added 40 | - Dependencies updated. 41 | - Command `gen-json` to generate sample JSON value from JSON Schema. 42 | - Support for STDIN via `-` file path. 43 | 44 | ### Changed 45 | - Terminal output now has trailing line break. 46 | 47 | ### Fixed 48 | - Disabled preloaded standard schemas. 49 | 50 | ## [1.8.8] - 2021-09-26 51 | 52 | ### Added 53 | - Dependencies updated. 54 | 55 | ## [1.8.7] - 2021-04-20 56 | 57 | ### Fixed 58 | - Out of memory error with infinite recursion in some JSON Schema references. 59 | 60 | ## [1.8.6] - 2021-04-20 61 | 62 | ### Added 63 | - Dependencies updated. 64 | 65 | ## [1.8.5] - 2021-04-20 66 | 67 | ### Added 68 | - Dependencies updated. 69 | 70 | ## [1.8.4] - 2021-04-07 71 | 72 | ### Added 73 | - Generation of JSDoc type definitions from JSON Schema with `gen-jsdoc`. 74 | 75 | ## [1.8.3] - 2020-12-14 76 | 77 | ### Fixed 78 | - Stale app version 79 | 80 | ## [1.8.2] - 2020-12-13 81 | 82 | ### Changed 83 | - Internal refactoring of CLI options. 84 | 85 | ## [1.8.1] - 2020-12-13 86 | 87 | ### Added 88 | - Dependencies updated. 89 | 90 | ## [1.8.0] - 2020-09-30 91 | 92 | ### Added 93 | - Dependencies updated. 94 | - Added schema patches to `gen-go` and `gen-php`. 95 | - Added property name fields controls in `gen-go`. 96 | 97 | ## [1.7.13] - 2020-09-26 98 | 99 | ### Added 100 | - Dependency `swaggest/json-diff` updated. 101 | 102 | ## [1.7.12] - 2020-09-25 103 | 104 | ### Added 105 | - Dependency `swaggest/json-diff` updated. 106 | 107 | ## [1.7.11] - 2020-09-22 108 | 109 | ### Added 110 | - Dependencies updated. 111 | 112 | ### Fixed 113 | - Removing empty destination directory when generating PHP classes, [#19](https://github.com/swaggest/json-cli/issues/19). 114 | 115 | ## [1.7.10] - 2020-05-20 116 | 117 | ### Added 118 | - Dependencies updated. 119 | 120 | ## [1.7.9] - 2020-04-29 121 | 122 | ### Added 123 | - Dependencies updated. 124 | 125 | ## [1.7.8] - 2020-04-28 126 | 127 | ### Changed 128 | - Hardcoded time limit for 60 seconds removed. 129 | 130 | ### Added 131 | - Option `--validate-required` to validate required properties during unmarshal in `gen-go`. 132 | - Dependencies updated. 133 | 134 | ## [1.7.7] - 2020-04-21 135 | 136 | ### Added 137 | - Dependencies updated. 138 | 139 | ## [1.7.6] - 2020-04-04 140 | 141 | ### Added 142 | - Option `--require-xgenerate` to generate properties with `x-generate: true` only in `gen-go`. 143 | 144 | ### Fixed 145 | - Handling of malformed JSONL in `build-schema`, invalid lines are skipped. 146 | 147 | ## [1.7.5] - 2020-03-30 148 | 149 | ### Added 150 | - Option to add multiple data samples in `build-schema`. 151 | - Option to add new line in `minify`. 152 | 153 | ### Fixed 154 | - Generated tests do not honor `--enable-default-additional-properties`. 155 | 156 | ## [1.7.4] - 2020-03-17 157 | 158 | ### Added 159 | - Option to rename generated symbols in `gen-go`. 160 | 161 | ## [1.7.3] - 2020-03-10 162 | 163 | ### Added 164 | - Dependencies updated. 165 | - Tests generator in `gen-go`. 166 | - Example collector in `build-schema`. 167 | 168 | ## [1.7.2] - 2020-02-25 169 | 170 | ### Added 171 | - Dependencies updated. 172 | - Backwards compatibility option `--ignore-required` in `gen-go` to ignore if property is required when deciding on pointer type or omitempty. 173 | 174 | ## [1.7.1] - 2020-02-02 175 | 176 | ### Added 177 | - Dependencies updated. 178 | 179 | ## [1.7.0] - 2020-01-26 180 | 181 | ### Added 182 | - Command to build JSON Schema from instance value(s). 183 | - Dependencies updated. 184 | 185 | ## [1.6.8] - 2020-01-24 186 | 187 | ### Added 188 | - Option to build accessors for additional properties in generated `PHP` classes. 189 | - Option to declare default values for properties in generated `PHP` classes. 190 | - Option to create and apply JSON Merge Patches (RFC 7386). 191 | 192 | ## [1.6.7] - 2020-01-04 193 | 194 | ### Added 195 | - Option to build fluent setters in generated `Go` structures. 196 | 197 | ## [1.6.6] - 2019-12-03 198 | 199 | ### Added 200 | - Dependencies updated to fix issues in `swaggest/php-code-builder` and `swaggest/php-json-schema`. 201 | 202 | ## [1.6.5] - 2019-11-18 203 | 204 | ### Added 205 | - Updated `swaggest/go-code-builder` to improve memory efficiency of generated `Go` structures. 206 | 207 | ## [1.6.4] - 2019-10-27 208 | 209 | ### Added 210 | - Dependencies updated. 211 | 212 | ## [1.6.3] - 2019-10-15 213 | 214 | ### Added 215 | - Option to disable null `additionalProperties` (`--enable-default-additional-properties`) rendering in `gen-go`. 216 | - Option to ignore [`x-go-type`](https://github.com/swaggest/go-code-builder#x-go-type) (`--ignore-xgo-type`) in `gen-go`. 217 | - Option to add `omitempty` on nullable types (`--ignore-nullable`) in `gen-go`. 218 | - Option to use pointer types to distinguish zero from unset (`--with-zero-values`) in `gen-go`. 219 | - Option to inherit nullability from [`x-nullable`/`nullable`](https://github.com/swaggest/go-code-builder#x-nullable-nullable) vendor extensions (`--enable-xnullable`) in `gen-go`. 220 | - Version of `json-cli` to head comment of `gen-go` output. 221 | 222 | ## [1.6.2] - 2019-09-22 223 | 224 | ### Added 225 | - Docker image. 226 | - Dependencies updated. 227 | 228 | ### Fixed 229 | - Local file resolver in references. 230 | 231 | [1.11.2]: https://github.com/swaggest/json-cli/compare/v1.11.1...v1.11.2 232 | [1.11.1]: https://github.com/swaggest/json-cli/compare/v1.10.1...v1.11.1 233 | [1.11.0]: https://github.com/swaggest/json-cli/compare/v1.10.0...v1.11.0 234 | [1.10.0]: https://github.com/swaggest/json-cli/compare/v1.9.1...v1.10.0 235 | [1.9.1]: https://github.com/swaggest/json-cli/compare/v1.9.0...v1.9.1 236 | [1.9.0]: https://github.com/swaggest/json-cli/compare/v1.8.8...v1.9.0 237 | [1.8.8]: https://github.com/swaggest/json-cli/compare/v1.8.7...v1.8.8 238 | [1.8.7]: https://github.com/swaggest/json-cli/compare/v1.8.6...v1.8.7 239 | [1.8.6]: https://github.com/swaggest/json-cli/compare/v1.8.5...v1.8.6 240 | [1.8.5]: https://github.com/swaggest/json-cli/compare/v1.8.4...v1.8.5 241 | [1.8.4]: https://github.com/swaggest/json-cli/compare/v1.8.3...v1.8.4 242 | [1.8.3]: https://github.com/swaggest/json-cli/compare/v1.8.2...v1.8.3 243 | [1.8.2]: https://github.com/swaggest/json-cli/compare/v1.8.1...v1.8.2 244 | [1.8.1]: https://github.com/swaggest/json-cli/compare/v1.8.0...v1.8.1 245 | [1.8.0]: https://github.com/swaggest/json-cli/compare/v1.7.13...v1.8.0 246 | [1.7.13]: https://github.com/swaggest/json-cli/compare/v1.7.12...v1.7.13 247 | [1.7.12]: https://github.com/swaggest/json-cli/compare/v1.7.11...v1.7.12 248 | [1.7.11]: https://github.com/swaggest/json-cli/compare/v1.7.10...v1.7.11 249 | [1.7.10]: https://github.com/swaggest/json-cli/compare/v1.7.9...v1.7.10 250 | [1.7.9]: https://github.com/swaggest/json-cli/compare/v1.7.8...v1.7.9 251 | [1.7.8]: https://github.com/swaggest/json-cli/compare/v1.7.7...v1.7.8 252 | [1.7.7]: https://github.com/swaggest/json-cli/compare/v1.7.6...v1.7.7 253 | [1.7.6]: https://github.com/swaggest/json-cli/compare/v1.7.5...v1.7.6 254 | [1.7.5]: https://github.com/swaggest/json-cli/compare/v1.7.4...v1.7.5 255 | [1.7.4]: https://github.com/swaggest/json-cli/compare/v1.7.3...v1.7.4 256 | [1.7.3]: https://github.com/swaggest/json-cli/compare/v1.7.2...v1.7.3 257 | [1.7.2]: https://github.com/swaggest/json-cli/compare/v1.7.1...v1.7.2 258 | [1.7.1]: https://github.com/swaggest/json-cli/compare/v1.7.0...v1.7.1 259 | [1.7.0]: https://github.com/swaggest/json-cli/compare/v1.6.8...v1.7.0 260 | [1.6.8]: https://github.com/swaggest/json-cli/compare/v1.6.7...v1.6.8 261 | [1.6.7]: https://github.com/swaggest/json-cli/compare/v1.6.6...v1.6.7 262 | [1.6.6]: https://github.com/swaggest/json-cli/compare/v1.6.5...v1.6.6 263 | [1.6.5]: https://github.com/swaggest/json-cli/compare/v1.6.4...v1.6.5 264 | [1.6.4]: https://github.com/swaggest/json-cli/compare/v1.6.3...v1.6.4 265 | [1.6.3]: https://github.com/swaggest/json-cli/compare/v1.6.2...v1.6.3 266 | [1.6.2]: https://github.com/swaggest/json-cli/compare/v1.6.1...v1.6.2 267 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSON CLI multitool 2 | 3 | Swiss Knife 4 | 5 | A CLI app to find unordered diff between two `JSON` documents (based 6 | on [`swaggest/json-diff`](https://github.com/swaggest/json-diff)), generate JSON Schema and Go/PHP code, pretty print, 7 | minify, yaml convert, etc.... 8 | 9 | [![Build Status](https://travis-ci.org/swaggest/json-cli.svg?branch=master)](https://travis-ci.org/swaggest/json-cli) 10 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/swaggest/json-cli/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/swaggest/json-cli/?branch=master) 11 | [![Code Climate](https://codeclimate.com/github/swaggest/json-cli/badges/gpa.svg)](https://codeclimate.com/github/swaggest/json-cli) 12 | [![Code Coverage](https://scrutinizer-ci.com/g/swaggest/json-cli/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/swaggest/json-cli/code-structure/master/code-coverage) 13 | [![Image Size](https://images.microbadger.com/badges/image/swaggest/json-cli.svg)](https://microbadger.com/images/swaggest/json-cli) 14 | ![Code lines](https://sloc.xyz/github/swaggest/json-cli/?category=code) 15 | ![Comments](https://sloc.xyz/github/swaggest/json-cli/?category=comments) 16 | 17 | ## Purpose 18 | 19 | * To simplify changes review between two `JSON` files you can use a standard `diff` tool on rearranged 20 | pretty-printed `JSON`. 21 | * To detect breaking changes by analyzing removals and changes from original `JSON`. 22 | * To keep original order of object sets (for 23 | example `swagger.json` [parameters](https://swagger.io/docs/specification/describing-parameters/) list). 24 | * To make and apply JSON Patches, specified in [RFC 6902](http://tools.ietf.org/html/rfc6902) from the IETF. 25 | * To convert between YAML/JSON/PHP serialization. 26 | * To resolve `JSON Pointer` to data. 27 | * To resolve `JSON Pointer` to file position. 28 | * To validate JSON data against [`JSON Schema`](http://json-schema.org/). 29 | * To [generate or update](#buildschema) JSON Schema with instance value(s). 30 | * To [generate](#genjson) sample JSON value from JSON Schema. 31 | * To [render](#gengo) `JSON Schema` as [`Go`](http://golang.org/) structure. 32 | * To [render](#genphp) `JSON Schema` as `PHP` classes. 33 | * To [render](#genjsdoc) `JSON Schema` as `JSDoc` type definitions. 34 | * To [render](#genmarkdown) `JSON Schema` as `Markdown` documentation. 35 | 36 | ## Installation 37 | 38 | ### Docker 39 | 40 | ``` 41 | docker run swaggest/json-cli json-cli --help 42 | v1.6.1 json-cli 43 | JSON CLI tool, https://github.com/swaggest/json-cli 44 | ... 45 | ``` 46 | 47 | `json-cli` can load schema from stdin (using `-` as a file path) which can be handy with docker, for example: 48 | 49 | ``` 50 | cat ./tests/assets/swagger-schema.json | docker run -i --rm swaggest/json-cli json-cli gen-jsdoc - 51 | ``` 52 | 53 | ### Composer 54 | 55 | [Install PHP Composer](https://getcomposer.org/doc/00-intro.md) 56 | 57 | ```bash 58 | composer require swaggest/json-cli 59 | ``` 60 | 61 | ## CLI tool 62 | 63 | ### Usage 64 | 65 | ``` 66 | v1.9.0 json-cli 67 | JSON CLI tool, https://github.com/swaggest/json-cli 68 | Usage: 69 | json-cli 70 | action Action name 71 | Allowed values: diff, apply, rearrange, diff-info, pretty-print, minify, replace, resolve, 72 | resolve-pos, validate-schema, gen-go, gen-php, gen-jsdoc, gen-json, build-schema 73 | ``` 74 | 75 | Input paths can be .json/.yaml/.yml/.serialized files, file format is detected by file extension: 76 | 77 | * `.json` JSON 78 | * `.yaml`, `.yml` YAML 79 | * `.serialized` PHP serialization format 80 | 81 | #### Diff, make `JSON Patch` from two documents 82 | 83 | ``` 84 | v1.3.0 json-cli diff 85 | JSON CLI tool, https://github.com/swaggest/json-cli 86 | Make patch from two json documents, output to STDOUT 87 | Usage: 88 | json-cli diff 89 | originalPath Path to old (original) json file 90 | newPath Path to new json file 91 | 92 | Options: 93 | --rearrange-arrays Rearrange arrays to match original 94 | --pretty Pretty-print result JSON 95 | --output Path to output result, default STDOUT 96 | --to-yaml Output in YAML format 97 | --pretty-short Pretty short format 98 | ``` 99 | 100 | Example: 101 | 102 | Making `JSON Patch` 103 | 104 | ``` 105 | json-cli diff tests/assets/original.json tests/assets/new.json --rearrange-arrays --pretty-short 106 | [ 107 | {"value":4,"op":"test","path":"/key1/0"}, 108 | {"value":5,"op":"replace","path":"/key1/0"}, 109 | {"op":"remove","path":"/key2"}, 110 | {"op":"remove","path":"/key3/sub0"}, 111 | {"value":"a","op":"test","path":"/key3/sub1"}, 112 | {"value":"c","op":"replace","path":"/key3/sub1"}, 113 | {"value":"b","op":"test","path":"/key3/sub2"}, 114 | {"value":false,"op":"replace","path":"/key3/sub2"}, 115 | {"value":0,"op":"add","path":"/key3/sub3"}, 116 | {"op":"remove","path":"/key4/1/b"}, 117 | {"value":false,"op":"add","path":"/key4/1/c"}, 118 | {"value":1,"op":"add","path":"/key4/2/c"}, 119 | {"value":"wat","op":"add","path":"/key5"} 120 | ] 121 | ``` 122 | 123 | #### Apply `JSON Patch` to document 124 | 125 | ``` 126 | v1.3.0 json-cli apply 127 | JSON CLI tool, https://github.com/swaggest/json-cli 128 | Apply patch to base json document, output to STDOUT 129 | Usage: 130 | json-cli apply [patchPath] [basePath] 131 | patchPath Path to JSON patch file 132 | basePath Path to JSON base file 133 | 134 | Options: 135 | --pretty Pretty-print result JSON 136 | --output Path to output result, default STDOUT 137 | --to-yaml Output in YAML format 138 | --tolerate-errors Continue on error 139 | ``` 140 | 141 | #### Rearrange JSON document to keep original order 142 | 143 | ``` 144 | v1.3.0 json-cli rearrange 145 | JSON CLI tool, https://github.com/swaggest/json-cli 146 | Rearrange json document in the order of another (original) json document 147 | Usage: 148 | json-cli rearrange 149 | originalPath Path to old (original) json file 150 | newPath Path to new json file 151 | 152 | Options: 153 | --rearrange-arrays Rearrange arrays to match original 154 | --pretty Pretty-print result JSON 155 | --output Path to output result, default STDOUT 156 | --to-yaml Output in YAML format 157 | ``` 158 | 159 | Example: 160 | 161 | Using with standard `diff` 162 | 163 | ``` 164 | json-cli rearrange tests/assets/original.json tests/assets/new.json --rearrange-arrays --pretty | diff <(json-cli pretty-print ./tests/assets/original.json) - 165 | 3c3 166 | < 4, 167 | --- 168 | > 5, 169 | 8d7 170 | < "key2": 2, 171 | 10,12c9,11 172 | < "sub0": 0, 173 | < "sub1": "a", 174 | < "sub2": "b" 175 | --- 176 | > "sub1": "c", 177 | > "sub2": false, 178 | > "sub3": 0 179 | 21c20 180 | < "b": false 181 | --- 182 | > "c": false 183 | 24c23,24 184 | < "a": 3 185 | --- 186 | > "a": 3, 187 | > "c": 1 188 | 26c26,27 189 | < ] 190 | --- 191 | > ], 192 | > "key5": "wat" 193 | ``` 194 | 195 | #### Show difference between two JSON documents 196 | 197 | ``` 198 | json-cli diff-info --help 199 | v1.3.0 json-cli diff-info 200 | JSON CLI tool, https://github.com/swaggest/json-cli 201 | Show diff info for two JSON documents 202 | Usage: 203 | json-cli diff-info 204 | originalPath Path to old (original) json file 205 | newPath Path to new json file 206 | 207 | Options: 208 | --rearrange-arrays Rearrange arrays to match original 209 | --pretty Pretty-print result JSON 210 | --output Path to output result, default STDOUT 211 | --to-yaml Output in YAML format 212 | --with-contents Add content to output 213 | --with-paths Add paths to output 214 | ``` 215 | 216 | Example: 217 | 218 | Showing differences in `JSON` mode 219 | 220 | ``` 221 | json-cli diff-info tests/assets/original.json tests/assets/new.json --with-paths --pretty 222 | { 223 | "addedCnt": 4, 224 | "modifiedCnt": 4, 225 | "removedCnt": 3, 226 | "addedPaths": [ 227 | "/key3/sub3", 228 | "/key4/0/c", 229 | "/key4/2/c", 230 | "/key5" 231 | ], 232 | "modifiedPaths": [ 233 | "/key1/0", 234 | "/key3/sub1", 235 | "/key3/sub2", 236 | "/key4/0/a", 237 | "/key4/1/a", 238 | "/key4/1/b" 239 | ], 240 | "removedPaths": [ 241 | "/key2", 242 | "/key3/sub0", 243 | "/key4/0/b" 244 | ] 245 | } 246 | ``` 247 | 248 | #### Pretty-print JSON document or convert between formats 249 | 250 | ``` 251 | json-cli pretty-print --help 252 | v1.4.2 json-cli pretty-print 253 | JSON CLI tool, https://github.com/swaggest/json-cli 254 | Pretty print JSON document 255 | Usage: 256 | json-cli pretty-print 257 | path Path to JSON/YAML file 258 | 259 | Options: 260 | --output Path to output result, default STDOUT 261 | --to-yaml Output in YAML format 262 | --to-serialized Output in PHP serialized format 263 | ``` 264 | 265 | #### Minify JSON document 266 | 267 | ``` 268 | json-cli minify --help 269 | v1.7.5 json-cli minify 270 | JSON CLI tool, https://github.com/swaggest/json-cli 271 | Minify JSON document 272 | Usage: 273 | json-cli minify 274 | path Path to JSON/YAML file 275 | 276 | Options: 277 | --output Path to output result, default STDOUT 278 | --to-serialized Output in PHP serialized format 279 | --eol Add line break to the output 280 | ``` 281 | 282 | Bash command to minify all JSON files in current directory. 283 | 284 | ``` 285 | for f in *.json; do json-cli minify $f --output $f; done 286 | ``` 287 | 288 | #### Replace values in JSON document 289 | 290 | ``` 291 | json-cli replace --help 292 | v1.3.0 json-cli replace 293 | JSON CLI tool, https://github.com/swaggest/json-cli 294 | Minify JSON document 295 | Usage: 296 | json-cli replace 297 | path Path to JSON/YAML file 298 | search Search JSON value 299 | replace Replace JSON value 300 | 301 | Options: 302 | --path-filter JSON path filter regex, example "/definitions/.*/properties/deletedAt" 303 | ``` 304 | 305 | Example: 306 | 307 | ``` 308 | json-cli replace swagger.json '{"type": "string","format": "date-time"}' '{"type": "string","format": "date-time","x-nullable":true}' --path-filter '/definitions/.*/properties/deletedAt' --output swagger-fixed.json 309 | ``` 310 | 311 | #### Resolve `JSON Pointer` to a value from document 312 | 313 | ``` 314 | json-cli resolve --help 315 | v1.3.0 json-cli resolve 316 | JSON CLI tool, https://github.com/swaggest/json-cli 317 | Usage: 318 | json-cli resolve [path] [pointer] 319 | path Path to JSON/YAML file 320 | pointer JSON Pointer, example /key4/1/a 321 | ``` 322 | 323 | Example: 324 | 325 | ``` 326 | json-cli resolve tests/assets/original.json /key4/1 327 | {"a":2,"b":false} 328 | ``` 329 | 330 | #### Resolve `JSON Pointer` to a position in JSON file (line:col) 331 | 332 | ``` 333 | json-cli resolve-pos --help 334 | v1.3.0 json-cli resolve-pos 335 | JSON CLI tool, https://github.com/swaggest/json-cli 336 | Usage: 337 | json-cli resolve-pos [path] [pointer] 338 | path Path to JSON file 339 | pointer JSON Pointer, example /key4/1/a 340 | 341 | Options: 342 | --dump-all Dump all pointer positions from JSON 343 | ``` 344 | 345 | Example: 346 | 347 | ``` 348 | json-cli resolve-pos tests/assets/original.json /key4/1 349 | 19:9 350 | ``` 351 | 352 | #### Validate JSON document against `JSON Schema` 353 | 354 | ``` 355 | json-cli validate-schema --help 356 | v1.4.0 json-cli validate-schema 357 | JSON CLI tool, https://github.com/swaggest/json-cli 358 | Usage: 359 | json-cli validate-schema [schema] 360 | data Path to data (JSON/YAML) 361 | schema Path to schema, default JSON Schema 362 | ``` 363 | 364 | Example: 365 | 366 | ``` 367 | json-cli validate-schema tests/assets/sample-data.json tests/assets/sample-schema.json 368 | Data is invalid 369 | No valid results for oneOf { 370 | 0: String expected, 5 received at #->oneOf[0] 371 | 1: Value more than 10 expected, 5 received at #->oneOf[1]->$ref[#/definitions/int10plus] 372 | } 373 | ``` 374 | 375 | #### Generate/update `JSON Schema` from instance value(s). 376 | 377 | New or existing schema is synchronized to match data samples. 378 | 379 | ``` 380 | v1.7.8 json-cli build-schema 381 | JSON CLI tool, https://github.com/swaggest/json-cli 382 | Usage: 383 | json-cli build-schema [schema] 384 | data Path to data (JSON/YAML) 385 | schema Path to parent schema 386 | 387 | Options: 388 | --ptr-in-schema JSON pointer to structure in root schema, default # 389 | --ptr-in-data JSON pointer to structure in data, default # 390 | --jsonl Data is a stream of JSON Lines 391 | --use-nullable Use `nullable: true` instead of `type: null`, OAS 3.0 compatibility 392 | --use-xnullable Use `x-nullable: true` instead of `type: null`, Swagger 2.0 compatibility 393 | --defs-ptr Location to put new definitions. default: "#/definitions/" 394 | --collect-examples Collect scalar values example 395 | --heuristic-required Mark properties that are available in all samples as `required`. 396 | --additional-data Additional paths to data 397 | --pretty Pretty-print result JSON 398 | --output Path to output result, default STDOUT 399 | --to-yaml Output in YAML format 400 | --to-serialized Output in PHP serialized format 401 | ``` 402 | 403 | Basic example: 404 | 405 | ``` 406 | json-cli build-schema tests/assets/original.json 407 | 408 | {"properties":{"key1":{"items":{"type":"integer"},"type":"array"},"key2":{"type":"integer"},"key3":{"$ref":"#/definitions/key3"},"key4":{"items":{"$ref":"#/definitions/key4.element"},"type":"array"}},"type":"object","definitions":{"key3":{"properties":{"sub0":{"type":"integer"},"sub1":{"type":"string"},"sub2":{"type":"string"}},"type":"object"},"key4.element":{"properties":{"a":{"type":"integer"},"b":{"type":"boolean"}},"type":"object"}}} 409 | ``` 410 | 411 | Advanced example: 412 | 413 | ``` 414 | json-cli build-schema dump-responses.jsonl ./acme-service/swagger.json --ptr-in-schema "#/definitions/Orders" --jsonl --ptr-in-data "#/responseValue" --pretty --output swagger.json 415 | ``` 416 | 417 | Updates `swagger.json` with actual response samples provided in `dump-responses.jsonl`. 418 | 419 | #### Generate [`Go`](http://golang.org/) structure from `JSON Schema`. 420 | 421 | `Go` code is built using [`swaggest/go-code-builder`](http://github.com/swaggest/go-code-builder). 422 | 423 | ``` 424 | v1.8.0 json-cli gen-go 425 | JSON CLI tool, https://github.com/swaggest/json-cli 426 | Generate Go code from JSON schema 427 | Usage: 428 | json-cli gen-go 429 | schema Path to JSON schema file 430 | 431 | Options: 432 | --ptr-in-schema JSON pointers to structure in root schema, default # 433 | --def-ptr Definitions pointers to strip from symbol names, default #/definitions 434 | --patches JSON patches to apply to schema file before processing, merge patches are also supported 435 | --output Path to output .go file, STDOUT is used by default 436 | --package-name Go package name, default "entities" 437 | --root-name Go root struct name, default "Structure", only used for # pointer 438 | --show-const-properties Show properties with constant values, hidden by default 439 | --keep-parent-in-property-names Keep parent prefix in property name, removed by default 440 | --ignore-nullable Add `omitempty` to nullable properties, removed by default 441 | --ignore-xgo-type Ignore `x-go-type` in schema to skip generation 442 | --with-zero-values Use pointer types to avoid zero value ambiguity 443 | --enable-xnullable Add `null` to types if `x-nullable` or `nullable` is available 444 | --enable-default-additional-properties Add field property for undefined `additionalProperties` 445 | --fluent-setters Add fluent setters to struct fields 446 | --ignore-required Ignore if property is required when deciding on pointer type or omitempty 447 | --renames Map of exported symbol renames, example From:To 448 | --with-tests Generate (un)marshaling tests for entities (experimental feature) 449 | --require-xgenerate Generate properties with `x-generate: true` only 450 | --validate-required Generate validation code to check required properties during unmarshal 451 | --name-tags Set additional field tags with property name, example "msgp bson" 452 | ``` 453 | 454 | Example: 455 | 456 | ``` 457 | json-cli gen-go http://json-schema.org/learn/examples/address.schema.json 458 | ``` 459 | 460 | ``` 461 | // Code generated by github.com/swaggest/json-cli v1.6.3, DO NOT EDIT. 462 | 463 | // Package entities contains JSON mapping structures. 464 | package entities 465 | 466 | 467 | 468 | // Structure structure is generated from "#". 469 | // 470 | // An address similar to http://microformats.org/wiki/h-card. 471 | type Structure struct { 472 | PostOfficeBox string `json:"post-office-box,omitempty"` 473 | ExtendedAddress string `json:"extended-address,omitempty"` 474 | StreetAddress string `json:"street-address,omitempty"` 475 | Locality string `json:"locality,omitempty"` 476 | Region string `json:"region,omitempty"` 477 | PostalCode string `json:"postal-code,omitempty"` 478 | CountryName string `json:"country-name,omitempty"` 479 | } 480 | ``` 481 | 482 | Advanced example: 483 | 484 | ``` 485 | json-cli gen-go "https://raw.githubusercontent.com/asyncapi/asyncapi/2.0.0-rc1/examples/1.2.0/streetlights.yml" \ 486 | --ptr-in-schema "#/components/messages/lightMeasured/payload" "#/components/messages/turnOnOff/payload" \ 487 | --def-ptr "#/components/schemas" \ 488 | --package-name message \ 489 | --output ./entities.go 490 | 491 | cat ./entities.go 492 | ``` 493 | 494 | ``` 495 | // Code generated by github.com/swaggest/json-cli v1.6.3, DO NOT EDIT. 496 | 497 | // Package message contains JSON mapping structures. 498 | package message 499 | 500 | import ( 501 | "fmt" 502 | "time" 503 | ) 504 | 505 | // LightMeasuredPayload structure is generated from "#/components/schemas/lightMeasuredPayload". 506 | type LightMeasuredPayload struct { 507 | Lumens int64 `json:"lumens,omitempty"` // Light intensity measured in lumens. 508 | SentAt *time.Time `json:"sentAt,omitempty"` // Date and time when the message was sent. 509 | } 510 | 511 | // TurnOnOffPayload structure is generated from "#/components/schemas/turnOnOffPayload". 512 | type TurnOnOffPayload struct { 513 | Command TurnOnOffPayloadCommand `json:"command,omitempty"` // Whether to turn on or off the light. 514 | SentAt *time.Time `json:"sentAt,omitempty"` // Date and time when the message was sent. 515 | } 516 | 517 | // TurnOnOffPayloadCommand is an enum type. 518 | type TurnOnOffPayloadCommand string 519 | 520 | // TurnOnOffPayloadCommand values enumeration. 521 | const ( 522 | TurnOnOffPayloadCommandOn = TurnOnOffPayloadCommand("on") 523 | TurnOnOffPayloadCommandOff = TurnOnOffPayloadCommand("off") 524 | ) 525 | 526 | // MarshalJSON encodes JSON. 527 | func (i TurnOnOffPayloadCommand) MarshalJSON() ([]byte, error) { 528 | switch i { 529 | case TurnOnOffPayloadCommandOn: 530 | case TurnOnOffPayloadCommandOff: 531 | 532 | default: 533 | return nil, fmt.Errorf("unexpected TurnOnOffPayloadCommand value: %v", i) 534 | } 535 | 536 | return json.Marshal(string(i)) 537 | } 538 | 539 | // UnmarshalJSON decodes JSON. 540 | func (i *TurnOnOffPayloadCommand) UnmarshalJSON(data []byte) error { 541 | var ii string 542 | err := json.Unmarshal(data, &ii) 543 | if err != nil { 544 | return err 545 | } 546 | v := TurnOnOffPayloadCommand(ii) 547 | switch v { 548 | case TurnOnOffPayloadCommandOn: 549 | case TurnOnOffPayloadCommandOff: 550 | 551 | default: 552 | return fmt.Errorf("unexpected TurnOnOffPayloadCommand value: %v", v) 553 | } 554 | 555 | *i = v 556 | return nil 557 | } 558 | ``` 559 | 560 | #### Generate `PHP` classes from `JSON Schema`. 561 | 562 | `PHP` code is built using [`swaggest/php-code-builder`](http://github.com/swaggest/php-code-builder). 563 | 564 | Generated classes require [`swaggest/json-schema`](http://github.com/swaggest/php-json-schema) package. 565 | 566 | ``` 567 | v1.8.0 json-cli gen-php 568 | JSON CLI tool, https://github.com/swaggest/json-cli 569 | Generate PHP code from JSON schema 570 | Usage: 571 | json-cli gen-php --ns --ns-path 572 | schema Path to JSON schema file 573 | 574 | Options: 575 | --ptr-in-schema JSON pointers to structure in root schema, default # 576 | --def-ptr Definitions pointers to strip from symbol names, default #/definitions 577 | --patches JSON patches to apply to schema file before processing, merge patches are also supported 578 | --ns Namespace to use for generated classes, example \MyClasses 579 | --ns-path Path to store generated classes, example ./src/MyClasses 580 | --root-name Go root struct name, default "Structure", only used for # pointer 581 | --setters Build setters 582 | --getters Build getters 583 | --no-enum-const Do not create constants for enum/const values 584 | --declare-property-defaults Use default values to initialize properties 585 | --build-additional-properties-accessors Build accessors for additionalProperties 586 | ``` 587 | 588 | Advanced example: 589 | 590 | ``` 591 | mkdir ./StreetLights 592 | 593 | json-cli gen-php "https://raw.githubusercontent.com/asyncapi/asyncapi/2.0.0-rc1/examples/1.2.0/streetlights.yml" \ 594 | --ptr-in-schema "#/components/messages/lightMeasured/payload" "#/components/messages/turnOnOff/payload" \ 595 | --def-ptr "#/components/schemas" \ 596 | --ns MyApp\\StreetLights \ 597 | --ns-path ./StreetLights 598 | 599 | cat ./StreetLights/* 600 | ``` 601 | 602 | ``` 603 | Classes are generated in /path/to/StreetLights 604 | 605 | lumens = Schema::integer(); 637 | $properties->lumens->description = "Light intensity measured in lumens."; 638 | $properties->lumens->minimum = 0; 639 | $properties->sentAt = Schema::string(); 640 | $properties->sentAt->description = "Date and time when the message was sent."; 641 | $properties->sentAt->format = "date-time"; 642 | $properties->sentAt->setFromRef('#/components/schemas/sentAt'); 643 | $ownerSchema->type = 'object'; 644 | $ownerSchema->components = (object)array( 645 | 'schemas' => 646 | (object)(array( 647 | 'sentAt' => 648 | (object)(array( 649 | 'description' => 'Date and time when the message was sent.', 650 | 'type' => 'string', 651 | 'format' => 'date-time', 652 | )), 653 | )), 654 | ); 655 | $ownerSchema->setFromRef('streetlights.yml#/components/messages/lightMeasured/payload'); 656 | } 657 | }command = Schema::string(); 693 | $properties->command->enum = array( 694 | self::ON, 695 | self::OFF, 696 | ); 697 | $properties->command->description = "Whether to turn on or off the light."; 698 | $properties->sentAt = Schema::string(); 699 | $properties->sentAt->description = "Date and time when the message was sent."; 700 | $properties->sentAt->format = "date-time"; 701 | $properties->sentAt->setFromRef('#/components/schemas/sentAt'); 702 | $ownerSchema->type = 'object'; 703 | $ownerSchema->components = (object)array( 704 | 'schemas' => 705 | (object)(array( 706 | 'sentAt' => 707 | (object)(array( 708 | 'description' => 'Date and time when the message was sent.', 709 | 'type' => 'string', 710 | 'format' => 'date-time', 711 | )), 712 | )), 713 | ); 714 | $ownerSchema->setFromRef('streetlights.yml#/components/messages/turnOnOff/payload'); 715 | } 716 | } 717 | ``` 718 | 719 | #### Generate `JSDoc` type definitions from `JSON Schema`. 720 | 721 | ``` 722 | v1.8.4 json-cli gen-jsdoc 723 | JSON CLI tool, https://github.com/swaggest/json-cli 724 | Generate JSDoc code from JSON schema 725 | Usage: 726 | json-cli gen-jsdoc 727 | schema Path to JSON schema file 728 | 729 | Options: 730 | --ptr-in-schema JSON pointers to structure in root schema, default # 731 | --def-ptr Definitions pointers to strip from symbol names, default #/definitions 732 | --patches JSON patches to apply to schema file before processing, merge patches are also supported 733 | ``` 734 | 735 | Example: 736 | 737 | ``` 738 | json-cli gen-jsdoc "https://raw.githubusercontent.com/asyncapi/asyncapi/2.0.0-rc1/examples/1.2.0/streetlights.yml" \ 739 | --ptr-in-schema "#/components/messages/lightMeasured/payload" "#/components/messages/turnOnOff/payload" \ 740 | --def-ptr "#/components/schemas" 741 | ``` 742 | 743 | ``` 744 | /** 745 | * @typedef ComponentsMessagesLightMeasuredPayload 746 | * @type {object} 747 | * @property {number} lumens - Light intensity measured in lumens. 748 | * @property {string} sentAt - Date and time when the message was sent. 749 | */ 750 | 751 | /** 752 | * @typedef ComponentsMessagesTurnOnOffPayload 753 | * @type {object} 754 | * @property {string} command - Whether to turn on or off the light. 755 | * @property {string} sentAt - Date and time when the message was sent. 756 | */ 757 | 758 | ``` 759 | 760 | #### Generate `Markdown` documentation from `JSON Schema`. 761 | 762 | ``` 763 | v1.10.0 json-cli gen-markdown 764 | JSON CLI tool, https://github.com/swaggest/json-cli 765 | Generate Markdown document from JSON schema 766 | Usage: 767 | json-cli gen-markdown 768 | schema Path to JSON schema file, use `-` for STDIN 769 | 770 | Options: 771 | --ptr-in-schema JSON pointers to structure in root schema, default # 772 | --def-ptr Definitions pointers to strip from symbol names, default #/definitions 773 | --patches JSON patches to apply to schema file before processing, merge patches are also supported 774 | ``` 775 | 776 | Example: 777 | 778 | ``` 779 | json-cli gen-markdown "https://raw.githubusercontent.com/asyncapi/asyncapi/2.0.0-rc1/examples/1.2.0/streetlights.yml" \ 780 | --ptr-in-schema "#/components/messages/lightMeasured/payload" "#/components/messages/turnOnOff/payload" \ 781 | --def-ptr "#/components/schemas" 782 | ``` 783 | 784 | ```markdown 785 | # Types 786 | 787 | * [`ComponentsMessagesLightMeasuredPayload`](#componentsmessageslightmeasuredpayload) 788 | * [`ComponentsMessagesTurnOnOffPayload`](#componentsmessagesturnonoffpayload) 789 | * [`LightMeasuredPayloadLumens`](#lightmeasuredpayloadlumens) 790 | 791 | 792 | 793 | 794 | ### ComponentsMessagesLightMeasuredPayload 795 | 796 | 797 | 798 | |Property|Type |Description | 799 | |--------|---------------------------------------------------------------------|----------------------------------------| 800 | |`lumens`|[`LightMeasuredPayloadLumens`](#lightmeasuredpayloadlumens), `Number`|Light intensity measured in lumens. | 801 | |`sentAt`|`String`, Format: `date-time` |Date and time when the message was sent.| 802 | 803 | 804 | ### ComponentsMessagesTurnOnOffPayload 805 | 806 | 807 | 808 | |Property |Type |Description | 809 | |---------|-----------------------------|----------------------------------------| 810 | |`command`|`'on'`,
`'off'` |Whether to turn on or off the light. | 811 | |`sentAt` |`String`, Format: `date-time`|Date and time when the message was sent.| 812 | 813 | 814 | ### LightMeasuredPayloadLumens 815 | Light intensity measured in lumens. 816 | 817 | |Constraint|Value| 818 | |----------|-----| 819 | |minimum |0 | 820 | ``` 821 | 822 | #### Generate `JSON` sample from `JSON Schema`. 823 | 824 | ``` 825 | v1.9.0 json-cli gen-json 826 | JSON CLI tool, https://github.com/swaggest/json-cli 827 | Generate JSON sample from JSON schema 828 | Usage: 829 | json-cli gen-json 830 | schema Path to JSON schema file, use `-` for STDIN 831 | 832 | Options: 833 | --ptr-in-schema JSON pointers to structure in root schema, default # 834 | --def-ptr Definitions pointers to strip from symbol names, default #/definitions 835 | --patches JSON patches to apply to schema file before processing, merge patches are also supported 836 | --max-nesting Max nesting level, default 10 837 | --default-additional-properties Treat non-existent `additionalProperties` as `additionalProperties: true` 838 | --rand-seed Integer random seed for deterministic output 839 | --pretty Pretty-print result JSON 840 | --output Path to output result, default STDOUT 841 | --to-yaml Output in YAML format 842 | --to-serialized Output in PHP serialized format 843 | ``` 844 | 845 | ``` 846 | echo '{ 847 | "properties": { 848 | "foo": { 849 | "type": "string", 850 | "example": "abc" 851 | }, 852 | "bar": { 853 | "enum": ["baz", "quux"] 854 | } 855 | } 856 | }' | ./bin/json-cli gen-json - --rand-seed 10 857 | ``` 858 | 859 | ``` 860 | {"foo":"abc","bar":"baz"} 861 | ``` -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "e763acf7fe1dd733ea38374ad557f764", 8 | "packages": [ 9 | { 10 | "name": "php-yaoi/php-yaoi", 11 | "version": "v1.0.40", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/php-yaoi/php-yaoi.git", 15 | "reference": "1d2a9b2409b6aad18d46c2b581eaac62101535a1" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/php-yaoi/php-yaoi/zipball/1d2a9b2409b6aad18d46c2b581eaac62101535a1", 20 | "reference": "1d2a9b2409b6aad18d46c2b581eaac62101535a1", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0" 25 | }, 26 | "require-dev": { 27 | "codeclimate/php-test-reporter": "0.1.2", 28 | "phpunit/phpunit": "4.8.23" 29 | }, 30 | "type": "library", 31 | "autoload": { 32 | "psr-4": { 33 | "Yaoi\\": "src/" 34 | } 35 | }, 36 | "notification-url": "https://packagist.org/downloads/", 37 | "license": [ 38 | "MIT" 39 | ], 40 | "authors": [ 41 | { 42 | "name": "Viacheslav Poturaev", 43 | "email": "vearutop@gmail.com", 44 | "homepage": "https://github.com/vearutop" 45 | } 46 | ], 47 | "description": "Yaoi is yet another object interleaver", 48 | "homepage": "https://github.com/php-yaoi/php-yaoi", 49 | "keywords": [ 50 | "framework" 51 | ], 52 | "support": { 53 | "issues": "https://github.com/php-yaoi/php-yaoi/issues", 54 | "source": "https://github.com/php-yaoi/php-yaoi/tree/master" 55 | }, 56 | "time": "2017-06-13T09:10:15+00:00" 57 | }, 58 | { 59 | "name": "phplang/scope-exit", 60 | "version": "1.0.0", 61 | "source": { 62 | "type": "git", 63 | "url": "https://github.com/phplang/scope-exit.git", 64 | "reference": "239b73abe89f9414aa85a7ca075ec9445629192b" 65 | }, 66 | "dist": { 67 | "type": "zip", 68 | "url": "https://api.github.com/repos/phplang/scope-exit/zipball/239b73abe89f9414aa85a7ca075ec9445629192b", 69 | "reference": "239b73abe89f9414aa85a7ca075ec9445629192b", 70 | "shasum": "" 71 | }, 72 | "require-dev": { 73 | "phpunit/phpunit": "*" 74 | }, 75 | "type": "library", 76 | "autoload": { 77 | "psr-4": { 78 | "PhpLang\\": "src/" 79 | } 80 | }, 81 | "notification-url": "https://packagist.org/downloads/", 82 | "license": [ 83 | "BSD" 84 | ], 85 | "authors": [ 86 | { 87 | "name": "Sara Golemon", 88 | "email": "pollita@php.net", 89 | "homepage": "https://twitter.com/SaraMG", 90 | "role": "Developer" 91 | } 92 | ], 93 | "description": "Emulation of SCOPE_EXIT construct from C++", 94 | "homepage": "https://github.com/phplang/scope-exit", 95 | "keywords": [ 96 | "cleanup", 97 | "exit", 98 | "scope" 99 | ], 100 | "support": { 101 | "issues": "https://github.com/phplang/scope-exit/issues", 102 | "source": "https://github.com/phplang/scope-exit/tree/master" 103 | }, 104 | "time": "2016-09-17T00:15:18+00:00" 105 | }, 106 | { 107 | "name": "salsify/json-streaming-parser", 108 | "version": "v7.0", 109 | "source": { 110 | "type": "git", 111 | "url": "https://github.com/salsify/jsonstreamingparser.git", 112 | "reference": "a4d8d651f01864ac539b6a05c3c781906a56bd2e" 113 | }, 114 | "dist": { 115 | "type": "zip", 116 | "url": "https://api.github.com/repos/salsify/jsonstreamingparser/zipball/a4d8d651f01864ac539b6a05c3c781906a56bd2e", 117 | "reference": "a4d8d651f01864ac539b6a05c3c781906a56bd2e", 118 | "shasum": "" 119 | }, 120 | "require": { 121 | "ext-mbstring": "*", 122 | "php": "^5.4 | ^7.0" 123 | }, 124 | "require-dev": { 125 | "phpunit/phpunit": "~4.0" 126 | }, 127 | "type": "library", 128 | "autoload": { 129 | "psr-4": { 130 | "JsonStreamingParser\\": "src", 131 | "JsonStreamingParser\\Test\\": "tests" 132 | } 133 | }, 134 | "notification-url": "https://packagist.org/downloads/", 135 | "license": [ 136 | "MIT" 137 | ], 138 | "authors": [ 139 | { 140 | "name": "Maxim Gnatenko", 141 | "email": "mgnatenko@gmail.com" 142 | }, 143 | { 144 | "name": "Rob Gonzalez", 145 | "email": "rob@salsify.com", 146 | "homepage": "http://salsify.com/" 147 | }, 148 | { 149 | "name": "Max Grigorian", 150 | "email": "maxakawizard@gmail.com", 151 | "homepage": "http://wizardcat.com/" 152 | } 153 | ], 154 | "description": "A streaming parser for JSON in PHP.", 155 | "homepage": "https://github.com/salsify/jsonstreamingparser", 156 | "keywords": [ 157 | "json", 158 | "parser", 159 | "streaming" 160 | ], 161 | "support": { 162 | "issues": "https://github.com/salsify/jsonstreamingparser/issues", 163 | "source": "https://github.com/salsify/jsonstreamingparser/tree/master" 164 | }, 165 | "time": "2018-03-29T00:35:18+00:00" 166 | }, 167 | { 168 | "name": "swaggest/code-builder", 169 | "version": "v0.3.8", 170 | "source": { 171 | "type": "git", 172 | "url": "https://github.com/swaggest/code-builder.git", 173 | "reference": "ffc1f70ab80cafbe39cd48ed9502ea8d365804ff" 174 | }, 175 | "dist": { 176 | "type": "zip", 177 | "url": "https://api.github.com/repos/swaggest/code-builder/zipball/ffc1f70ab80cafbe39cd48ed9502ea8d365804ff", 178 | "reference": "ffc1f70ab80cafbe39cd48ed9502ea8d365804ff", 179 | "shasum": "" 180 | }, 181 | "require": { 182 | "php": ">=5.4.0", 183 | "php-yaoi/php-yaoi": "*" 184 | }, 185 | "require-dev": { 186 | "phperf/phpunit": "4.8.37" 187 | }, 188 | "type": "library", 189 | "autoload": { 190 | "psr-4": { 191 | "Swaggest\\CodeBuilder\\": "src/" 192 | } 193 | }, 194 | "notification-url": "https://packagist.org/downloads/", 195 | "license": [ 196 | "MIT" 197 | ], 198 | "authors": [ 199 | { 200 | "name": "Viacheslav Poturaev", 201 | "email": "vearutop@gmail.com", 202 | "homepage": "https://github.com/vearutop" 203 | } 204 | ], 205 | "description": "Code generation library", 206 | "homepage": "https://github.com/swaggest/code-builder", 207 | "keywords": [ 208 | "library" 209 | ], 210 | "support": { 211 | "issues": "https://github.com/swaggest/code-builder/issues", 212 | "source": "https://github.com/swaggest/code-builder/tree/v0.3.8" 213 | }, 214 | "time": "2023-08-03T16:30:39+00:00" 215 | }, 216 | { 217 | "name": "swaggest/go-code-builder", 218 | "version": "v0.4.51", 219 | "source": { 220 | "type": "git", 221 | "url": "https://github.com/swaggest/go-code-builder.git", 222 | "reference": "6c65decec29528d81f886eb59593a67d4f7c4ddf" 223 | }, 224 | "dist": { 225 | "type": "zip", 226 | "url": "https://api.github.com/repos/swaggest/go-code-builder/zipball/6c65decec29528d81f886eb59593a67d4f7c4ddf", 227 | "reference": "6c65decec29528d81f886eb59593a67d4f7c4ddf", 228 | "shasum": "" 229 | }, 230 | "require": { 231 | "ext-json": "*", 232 | "php": ">=5.6.0", 233 | "phplang/scope-exit": "^1.0", 234 | "swaggest/code-builder": "^0.3.1|dev-master", 235 | "swaggest/json-schema": "^0.12.37", 236 | "swaggest/json-schema-maker": "^0.3.2" 237 | }, 238 | "require-dev": { 239 | "phperf/phpunit": "4.8.37", 240 | "victorjonsson/markdowndocs": "^1.3" 241 | }, 242 | "type": "library", 243 | "autoload": { 244 | "psr-4": { 245 | "Swaggest\\GoCodeBuilder\\": "src/" 246 | } 247 | }, 248 | "notification-url": "https://packagist.org/downloads/", 249 | "license": [ 250 | "MIT" 251 | ], 252 | "authors": [ 253 | { 254 | "name": "Viacheslav Poturaev", 255 | "email": "vearutop@gmail.com", 256 | "homepage": "https://github.com/vearutop" 257 | } 258 | ], 259 | "description": "GO code generation library", 260 | "homepage": "https://github.com/swaggest/go-code-builder", 261 | "keywords": [ 262 | "library" 263 | ], 264 | "support": { 265 | "issues": "https://github.com/swaggest/go-code-builder/issues", 266 | "source": "https://github.com/swaggest/go-code-builder/tree/v0.4.51" 267 | }, 268 | "time": "2022-09-15T08:12:33+00:00" 269 | }, 270 | { 271 | "name": "swaggest/json-diff", 272 | "version": "v3.10.5", 273 | "source": { 274 | "type": "git", 275 | "url": "https://github.com/swaggest/json-diff.git", 276 | "reference": "17bfc66b330f46e12a7e574133497a290cd79ba5" 277 | }, 278 | "dist": { 279 | "type": "zip", 280 | "url": "https://api.github.com/repos/swaggest/json-diff/zipball/17bfc66b330f46e12a7e574133497a290cd79ba5", 281 | "reference": "17bfc66b330f46e12a7e574133497a290cd79ba5", 282 | "shasum": "" 283 | }, 284 | "require": { 285 | "ext-json": "*" 286 | }, 287 | "require-dev": { 288 | "phperf/phpunit": "4.8.37" 289 | }, 290 | "type": "library", 291 | "autoload": { 292 | "psr-4": { 293 | "Swaggest\\JsonDiff\\": "src/" 294 | } 295 | }, 296 | "notification-url": "https://packagist.org/downloads/", 297 | "license": [ 298 | "MIT" 299 | ], 300 | "authors": [ 301 | { 302 | "name": "Viacheslav Poturaev", 303 | "email": "vearutop@gmail.com" 304 | } 305 | ], 306 | "description": "JSON diff/rearrange/patch/pointer library for PHP", 307 | "support": { 308 | "issues": "https://github.com/swaggest/json-diff/issues", 309 | "source": "https://github.com/swaggest/json-diff/tree/v3.10.5" 310 | }, 311 | "time": "2023-11-17T11:12:46+00:00" 312 | }, 313 | { 314 | "name": "swaggest/json-schema", 315 | "version": "v0.12.42", 316 | "source": { 317 | "type": "git", 318 | "url": "https://github.com/swaggest/php-json-schema.git", 319 | "reference": "d23adb53808b8e2da36f75bc0188546e4cbe3b45" 320 | }, 321 | "dist": { 322 | "type": "zip", 323 | "url": "https://api.github.com/repos/swaggest/php-json-schema/zipball/d23adb53808b8e2da36f75bc0188546e4cbe3b45", 324 | "reference": "d23adb53808b8e2da36f75bc0188546e4cbe3b45", 325 | "shasum": "" 326 | }, 327 | "require": { 328 | "ext-json": "*", 329 | "php": ">=5.4", 330 | "phplang/scope-exit": "^1.0", 331 | "swaggest/json-diff": "^3.8.2", 332 | "symfony/polyfill-mbstring": "^1.19" 333 | }, 334 | "require-dev": { 335 | "phperf/phpunit": "4.8.37" 336 | }, 337 | "suggest": { 338 | "ext-mbstring": "For better performance" 339 | }, 340 | "type": "library", 341 | "autoload": { 342 | "psr-4": { 343 | "Swaggest\\JsonSchema\\": "src/" 344 | } 345 | }, 346 | "notification-url": "https://packagist.org/downloads/", 347 | "license": [ 348 | "MIT" 349 | ], 350 | "authors": [ 351 | { 352 | "name": "Viacheslav Poturaev", 353 | "email": "vearutop@gmail.com" 354 | } 355 | ], 356 | "description": "High definition PHP structures with JSON-schema based validation", 357 | "support": { 358 | "email": "vearutop@gmail.com", 359 | "issues": "https://github.com/swaggest/php-json-schema/issues", 360 | "source": "https://github.com/swaggest/php-json-schema/tree/v0.12.42" 361 | }, 362 | "time": "2023-09-12T14:43:42+00:00" 363 | }, 364 | { 365 | "name": "swaggest/json-schema-maker", 366 | "version": "v0.3.7", 367 | "source": { 368 | "type": "git", 369 | "url": "https://github.com/swaggest/json-schema-maker.git", 370 | "reference": "303e60ceff94e84af95c68b4ac3e9e76dcc2ece8" 371 | }, 372 | "dist": { 373 | "type": "zip", 374 | "url": "https://api.github.com/repos/swaggest/json-schema-maker/zipball/303e60ceff94e84af95c68b4ac3e9e76dcc2ece8", 375 | "reference": "303e60ceff94e84af95c68b4ac3e9e76dcc2ece8", 376 | "shasum": "" 377 | }, 378 | "require": { 379 | "ext-json": "*", 380 | "php": ">=5.6.0", 381 | "swaggest/json-schema": "^0.12.27" 382 | }, 383 | "require-dev": { 384 | "phpunit/phpunit": "^5" 385 | }, 386 | "type": "library", 387 | "autoload": { 388 | "psr-4": { 389 | "Swaggest\\JsonSchemaMaker\\": "src/" 390 | } 391 | }, 392 | "notification-url": "https://packagist.org/downloads/", 393 | "license": [ 394 | "MIT" 395 | ], 396 | "authors": [ 397 | { 398 | "name": "Viacheslav Poturaev", 399 | "email": "vearutop@gmail.com", 400 | "homepage": "https://github.com/vearutop" 401 | } 402 | ], 403 | "description": "Instance to JSON schema and back", 404 | "homepage": "https://github.com/swaggest/json-schema-maker", 405 | "keywords": [ 406 | "json-schema" 407 | ], 408 | "support": { 409 | "issues": "https://github.com/swaggest/json-schema-maker/issues", 410 | "source": "https://github.com/swaggest/json-schema-maker/tree/v0.3.7" 411 | }, 412 | "time": "2021-10-28T21:58:11+00:00" 413 | }, 414 | { 415 | "name": "swaggest/php-code-builder", 416 | "version": "v0.2.41", 417 | "source": { 418 | "type": "git", 419 | "url": "https://github.com/swaggest/php-code-builder.git", 420 | "reference": "2f6ad5057c14d4842cf8b35d929a4b0813da39f5" 421 | }, 422 | "dist": { 423 | "type": "zip", 424 | "url": "https://api.github.com/repos/swaggest/php-code-builder/zipball/2f6ad5057c14d4842cf8b35d929a4b0813da39f5", 425 | "reference": "2f6ad5057c14d4842cf8b35d929a4b0813da39f5", 426 | "shasum": "" 427 | }, 428 | "require": { 429 | "ext-json": "*", 430 | "php": ">=5.6.0", 431 | "swaggest/code-builder": "^0.3.8", 432 | "swaggest/json-schema": "^0.12.33" 433 | }, 434 | "require-dev": { 435 | "phperf/phpunit": "4.8.38" 436 | }, 437 | "type": "library", 438 | "autoload": { 439 | "psr-4": { 440 | "Swaggest\\PhpCodeBuilder\\": "src/" 441 | } 442 | }, 443 | "notification-url": "https://packagist.org/downloads/", 444 | "license": [ 445 | "MIT" 446 | ], 447 | "authors": [ 448 | { 449 | "name": "Viacheslav Poturaev", 450 | "email": "vearutop@gmail.com", 451 | "homepage": "https://github.com/vearutop" 452 | } 453 | ], 454 | "description": "Swaggest JSON-schema enabled PHP code builder", 455 | "homepage": "https://github.com/swaggest/php-code-builder", 456 | "keywords": [ 457 | "library" 458 | ], 459 | "support": { 460 | "issues": "https://github.com/swaggest/php-code-builder/issues", 461 | "source": "https://github.com/swaggest/php-code-builder/tree/v0.2.41" 462 | }, 463 | "time": "2023-12-19T00:40:11+00:00" 464 | }, 465 | { 466 | "name": "symfony/polyfill-ctype", 467 | "version": "v1.19.0", 468 | "source": { 469 | "type": "git", 470 | "url": "https://github.com/symfony/polyfill-ctype.git", 471 | "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b" 472 | }, 473 | "dist": { 474 | "type": "zip", 475 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b", 476 | "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b", 477 | "shasum": "" 478 | }, 479 | "require": { 480 | "php": ">=5.3.3" 481 | }, 482 | "suggest": { 483 | "ext-ctype": "For best performance" 484 | }, 485 | "type": "library", 486 | "extra": { 487 | "branch-alias": { 488 | "dev-main": "1.19-dev" 489 | }, 490 | "thanks": { 491 | "name": "symfony/polyfill", 492 | "url": "https://github.com/symfony/polyfill" 493 | } 494 | }, 495 | "autoload": { 496 | "files": [ 497 | "bootstrap.php" 498 | ], 499 | "psr-4": { 500 | "Symfony\\Polyfill\\Ctype\\": "" 501 | } 502 | }, 503 | "notification-url": "https://packagist.org/downloads/", 504 | "license": [ 505 | "MIT" 506 | ], 507 | "authors": [ 508 | { 509 | "name": "Gert de Pagter", 510 | "email": "BackEndTea@gmail.com" 511 | }, 512 | { 513 | "name": "Symfony Community", 514 | "homepage": "https://symfony.com/contributors" 515 | } 516 | ], 517 | "description": "Symfony polyfill for ctype functions", 518 | "homepage": "https://symfony.com", 519 | "keywords": [ 520 | "compatibility", 521 | "ctype", 522 | "polyfill", 523 | "portable" 524 | ], 525 | "support": { 526 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0" 527 | }, 528 | "funding": [ 529 | { 530 | "url": "https://symfony.com/sponsor", 531 | "type": "custom" 532 | }, 533 | { 534 | "url": "https://github.com/fabpot", 535 | "type": "github" 536 | }, 537 | { 538 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 539 | "type": "tidelift" 540 | } 541 | ], 542 | "time": "2020-10-23T09:01:57+00:00" 543 | }, 544 | { 545 | "name": "symfony/polyfill-mbstring", 546 | "version": "v1.19.0", 547 | "source": { 548 | "type": "git", 549 | "url": "https://github.com/symfony/polyfill-mbstring.git", 550 | "reference": "b5f7b932ee6fa802fc792eabd77c4c88084517ce" 551 | }, 552 | "dist": { 553 | "type": "zip", 554 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b5f7b932ee6fa802fc792eabd77c4c88084517ce", 555 | "reference": "b5f7b932ee6fa802fc792eabd77c4c88084517ce", 556 | "shasum": "" 557 | }, 558 | "require": { 559 | "php": ">=5.3.3" 560 | }, 561 | "suggest": { 562 | "ext-mbstring": "For best performance" 563 | }, 564 | "type": "library", 565 | "extra": { 566 | "branch-alias": { 567 | "dev-main": "1.19-dev" 568 | }, 569 | "thanks": { 570 | "name": "symfony/polyfill", 571 | "url": "https://github.com/symfony/polyfill" 572 | } 573 | }, 574 | "autoload": { 575 | "files": [ 576 | "bootstrap.php" 577 | ], 578 | "psr-4": { 579 | "Symfony\\Polyfill\\Mbstring\\": "" 580 | } 581 | }, 582 | "notification-url": "https://packagist.org/downloads/", 583 | "license": [ 584 | "MIT" 585 | ], 586 | "authors": [ 587 | { 588 | "name": "Nicolas Grekas", 589 | "email": "p@tchwork.com" 590 | }, 591 | { 592 | "name": "Symfony Community", 593 | "homepage": "https://symfony.com/contributors" 594 | } 595 | ], 596 | "description": "Symfony polyfill for the Mbstring extension", 597 | "homepage": "https://symfony.com", 598 | "keywords": [ 599 | "compatibility", 600 | "mbstring", 601 | "polyfill", 602 | "portable", 603 | "shim" 604 | ], 605 | "support": { 606 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.19.0" 607 | }, 608 | "funding": [ 609 | { 610 | "url": "https://symfony.com/sponsor", 611 | "type": "custom" 612 | }, 613 | { 614 | "url": "https://github.com/fabpot", 615 | "type": "github" 616 | }, 617 | { 618 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 619 | "type": "tidelift" 620 | } 621 | ], 622 | "time": "2020-10-23T09:01:57+00:00" 623 | }, 624 | { 625 | "name": "symfony/yaml", 626 | "version": "v3.4.47", 627 | "source": { 628 | "type": "git", 629 | "url": "https://github.com/symfony/yaml.git", 630 | "reference": "88289caa3c166321883f67fe5130188ebbb47094" 631 | }, 632 | "dist": { 633 | "type": "zip", 634 | "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094", 635 | "reference": "88289caa3c166321883f67fe5130188ebbb47094", 636 | "shasum": "" 637 | }, 638 | "require": { 639 | "php": "^5.5.9|>=7.0.8", 640 | "symfony/polyfill-ctype": "~1.8" 641 | }, 642 | "conflict": { 643 | "symfony/console": "<3.4" 644 | }, 645 | "require-dev": { 646 | "symfony/console": "~3.4|~4.0" 647 | }, 648 | "suggest": { 649 | "symfony/console": "For validating YAML files using the lint command" 650 | }, 651 | "type": "library", 652 | "autoload": { 653 | "psr-4": { 654 | "Symfony\\Component\\Yaml\\": "" 655 | }, 656 | "exclude-from-classmap": [ 657 | "/Tests/" 658 | ] 659 | }, 660 | "notification-url": "https://packagist.org/downloads/", 661 | "license": [ 662 | "MIT" 663 | ], 664 | "authors": [ 665 | { 666 | "name": "Fabien Potencier", 667 | "email": "fabien@symfony.com" 668 | }, 669 | { 670 | "name": "Symfony Community", 671 | "homepage": "https://symfony.com/contributors" 672 | } 673 | ], 674 | "description": "Symfony Yaml Component", 675 | "homepage": "https://symfony.com", 676 | "support": { 677 | "source": "https://github.com/symfony/yaml/tree/v3.4.47" 678 | }, 679 | "funding": [ 680 | { 681 | "url": "https://symfony.com/sponsor", 682 | "type": "custom" 683 | }, 684 | { 685 | "url": "https://github.com/fabpot", 686 | "type": "github" 687 | }, 688 | { 689 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 690 | "type": "tidelift" 691 | } 692 | ], 693 | "time": "2020-10-24T10:57:07+00:00" 694 | } 695 | ], 696 | "packages-dev": [ 697 | { 698 | "name": "doctrine/instantiator", 699 | "version": "1.0.5", 700 | "source": { 701 | "type": "git", 702 | "url": "https://github.com/doctrine/instantiator.git", 703 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 704 | }, 705 | "dist": { 706 | "type": "zip", 707 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 708 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 709 | "shasum": "" 710 | }, 711 | "require": { 712 | "php": ">=5.3,<8.0-DEV" 713 | }, 714 | "require-dev": { 715 | "athletic/athletic": "~0.1.8", 716 | "ext-pdo": "*", 717 | "ext-phar": "*", 718 | "phpunit/phpunit": "~4.0", 719 | "squizlabs/php_codesniffer": "~2.0" 720 | }, 721 | "type": "library", 722 | "extra": { 723 | "branch-alias": { 724 | "dev-master": "1.0.x-dev" 725 | } 726 | }, 727 | "autoload": { 728 | "psr-4": { 729 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 730 | } 731 | }, 732 | "notification-url": "https://packagist.org/downloads/", 733 | "license": [ 734 | "MIT" 735 | ], 736 | "authors": [ 737 | { 738 | "name": "Marco Pivetta", 739 | "email": "ocramius@gmail.com", 740 | "homepage": "http://ocramius.github.com/" 741 | } 742 | ], 743 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 744 | "homepage": "https://github.com/doctrine/instantiator", 745 | "keywords": [ 746 | "constructor", 747 | "instantiate" 748 | ], 749 | "support": { 750 | "issues": "https://github.com/doctrine/instantiator/issues", 751 | "source": "https://github.com/doctrine/instantiator/tree/1.0.5" 752 | }, 753 | "funding": [ 754 | { 755 | "url": "https://www.doctrine-project.org/sponsorship.html", 756 | "type": "custom" 757 | }, 758 | { 759 | "url": "https://www.patreon.com/phpdoctrine", 760 | "type": "patreon" 761 | }, 762 | { 763 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 764 | "type": "tidelift" 765 | } 766 | ], 767 | "time": "2015-06-14T21:17:01+00:00" 768 | }, 769 | { 770 | "name": "phpdocumentor/reflection-common", 771 | "version": "1.0.1", 772 | "source": { 773 | "type": "git", 774 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 775 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 776 | }, 777 | "dist": { 778 | "type": "zip", 779 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 780 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 781 | "shasum": "" 782 | }, 783 | "require": { 784 | "php": ">=5.5" 785 | }, 786 | "require-dev": { 787 | "phpunit/phpunit": "^4.6" 788 | }, 789 | "type": "library", 790 | "extra": { 791 | "branch-alias": { 792 | "dev-master": "1.0.x-dev" 793 | } 794 | }, 795 | "autoload": { 796 | "psr-4": { 797 | "phpDocumentor\\Reflection\\": [ 798 | "src" 799 | ] 800 | } 801 | }, 802 | "notification-url": "https://packagist.org/downloads/", 803 | "license": [ 804 | "MIT" 805 | ], 806 | "authors": [ 807 | { 808 | "name": "Jaap van Otterdijk", 809 | "email": "opensource@ijaap.nl" 810 | } 811 | ], 812 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 813 | "homepage": "http://www.phpdoc.org", 814 | "keywords": [ 815 | "FQSEN", 816 | "phpDocumentor", 817 | "phpdoc", 818 | "reflection", 819 | "static analysis" 820 | ], 821 | "support": { 822 | "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", 823 | "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" 824 | }, 825 | "time": "2017-09-11T18:02:19+00:00" 826 | }, 827 | { 828 | "name": "phpdocumentor/reflection-docblock", 829 | "version": "3.3.2", 830 | "source": { 831 | "type": "git", 832 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 833 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" 834 | }, 835 | "dist": { 836 | "type": "zip", 837 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", 838 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", 839 | "shasum": "" 840 | }, 841 | "require": { 842 | "php": "^5.6 || ^7.0", 843 | "phpdocumentor/reflection-common": "^1.0.0", 844 | "phpdocumentor/type-resolver": "^0.4.0", 845 | "webmozart/assert": "^1.0" 846 | }, 847 | "require-dev": { 848 | "mockery/mockery": "^0.9.4", 849 | "phpunit/phpunit": "^4.4" 850 | }, 851 | "type": "library", 852 | "autoload": { 853 | "psr-4": { 854 | "phpDocumentor\\Reflection\\": [ 855 | "src/" 856 | ] 857 | } 858 | }, 859 | "notification-url": "https://packagist.org/downloads/", 860 | "license": [ 861 | "MIT" 862 | ], 863 | "authors": [ 864 | { 865 | "name": "Mike van Riel", 866 | "email": "me@mikevanriel.com" 867 | } 868 | ], 869 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 870 | "support": { 871 | "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", 872 | "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/3.x" 873 | }, 874 | "time": "2017-11-10T14:09:06+00:00" 875 | }, 876 | { 877 | "name": "phpdocumentor/type-resolver", 878 | "version": "0.4.0", 879 | "source": { 880 | "type": "git", 881 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 882 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 883 | }, 884 | "dist": { 885 | "type": "zip", 886 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 887 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 888 | "shasum": "" 889 | }, 890 | "require": { 891 | "php": "^5.5 || ^7.0", 892 | "phpdocumentor/reflection-common": "^1.0" 893 | }, 894 | "require-dev": { 895 | "mockery/mockery": "^0.9.4", 896 | "phpunit/phpunit": "^5.2||^4.8.24" 897 | }, 898 | "type": "library", 899 | "extra": { 900 | "branch-alias": { 901 | "dev-master": "1.0.x-dev" 902 | } 903 | }, 904 | "autoload": { 905 | "psr-4": { 906 | "phpDocumentor\\Reflection\\": [ 907 | "src/" 908 | ] 909 | } 910 | }, 911 | "notification-url": "https://packagist.org/downloads/", 912 | "license": [ 913 | "MIT" 914 | ], 915 | "authors": [ 916 | { 917 | "name": "Mike van Riel", 918 | "email": "me@mikevanriel.com" 919 | } 920 | ], 921 | "support": { 922 | "issues": "https://github.com/phpDocumentor/TypeResolver/issues", 923 | "source": "https://github.com/phpDocumentor/TypeResolver/tree/master" 924 | }, 925 | "time": "2017-07-14T14:27:02+00:00" 926 | }, 927 | { 928 | "name": "phperf/phpunit", 929 | "version": "4.8.38", 930 | "source": { 931 | "type": "git", 932 | "url": "https://github.com/phperf/phpunit.git", 933 | "reference": "34de0591973c2603bae61514070e7861a1966776" 934 | }, 935 | "dist": { 936 | "type": "zip", 937 | "url": "https://api.github.com/repos/phperf/phpunit/zipball/34de0591973c2603bae61514070e7861a1966776", 938 | "reference": "34de0591973c2603bae61514070e7861a1966776", 939 | "shasum": "" 940 | }, 941 | "require": { 942 | "ext-dom": "*", 943 | "ext-json": "*", 944 | "ext-pcre": "*", 945 | "ext-reflection": "*", 946 | "ext-spl": "*", 947 | "php": ">=5.3.3", 948 | "phpspec/prophecy": "^1.3.1", 949 | "phpunit/php-code-coverage": "~2.1", 950 | "phpunit/php-file-iterator": "~1.4", 951 | "phpunit/php-text-template": "~1.2", 952 | "phpunit/php-timer": "^1.0.6", 953 | "phpunit/phpunit-mock-objects": "~2.3", 954 | "sebastian/comparator": "~1.2.2", 955 | "sebastian/diff": "~1.2", 956 | "sebastian/environment": "~1.3", 957 | "sebastian/exporter": "~1.2", 958 | "sebastian/global-state": "~1.0", 959 | "sebastian/version": "~1.0", 960 | "symfony/yaml": "~2.1|~3.0" 961 | }, 962 | "suggest": { 963 | "phpunit/php-invoker": "~1.1" 964 | }, 965 | "bin": [ 966 | "phpunit" 967 | ], 968 | "type": "library", 969 | "extra": { 970 | "branch-alias": { 971 | "dev-master": "4.8.x-dev" 972 | } 973 | }, 974 | "autoload": { 975 | "files": [ 976 | "src/Facade.php", 977 | "src/Factory.php", 978 | "src/Iterator.php" 979 | ], 980 | "classmap": [ 981 | "src/" 982 | ] 983 | }, 984 | "notification-url": "https://packagist.org/downloads/", 985 | "license": [ 986 | "BSD-3-Clause" 987 | ], 988 | "authors": [ 989 | { 990 | "name": "Sebastian Bergmann", 991 | "email": "sebastian@phpunit.de", 992 | "role": "lead" 993 | } 994 | ], 995 | "description": "The PHP Unit Testing framework.", 996 | "homepage": "https://phpunit.de/", 997 | "keywords": [ 998 | "phpunit", 999 | "testing", 1000 | "xunit" 1001 | ], 1002 | "support": { 1003 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 1004 | "source": "https://github.com/phperf/phpunit/tree/4.8.38" 1005 | }, 1006 | "time": "2022-04-28T19:15:24+00:00" 1007 | }, 1008 | { 1009 | "name": "phpspec/prophecy", 1010 | "version": "v1.10.3", 1011 | "source": { 1012 | "type": "git", 1013 | "url": "https://github.com/phpspec/prophecy.git", 1014 | "reference": "451c3cd1418cf640de218914901e51b064abb093" 1015 | }, 1016 | "dist": { 1017 | "type": "zip", 1018 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", 1019 | "reference": "451c3cd1418cf640de218914901e51b064abb093", 1020 | "shasum": "" 1021 | }, 1022 | "require": { 1023 | "doctrine/instantiator": "^1.0.2", 1024 | "php": "^5.3|^7.0", 1025 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", 1026 | "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", 1027 | "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" 1028 | }, 1029 | "require-dev": { 1030 | "phpspec/phpspec": "^2.5 || ^3.2", 1031 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 1032 | }, 1033 | "type": "library", 1034 | "extra": { 1035 | "branch-alias": { 1036 | "dev-master": "1.10.x-dev" 1037 | } 1038 | }, 1039 | "autoload": { 1040 | "psr-4": { 1041 | "Prophecy\\": "src/Prophecy" 1042 | } 1043 | }, 1044 | "notification-url": "https://packagist.org/downloads/", 1045 | "license": [ 1046 | "MIT" 1047 | ], 1048 | "authors": [ 1049 | { 1050 | "name": "Konstantin Kudryashov", 1051 | "email": "ever.zet@gmail.com", 1052 | "homepage": "http://everzet.com" 1053 | }, 1054 | { 1055 | "name": "Marcello Duarte", 1056 | "email": "marcello.duarte@gmail.com" 1057 | } 1058 | ], 1059 | "description": "Highly opinionated mocking framework for PHP 5.3+", 1060 | "homepage": "https://github.com/phpspec/prophecy", 1061 | "keywords": [ 1062 | "Double", 1063 | "Dummy", 1064 | "fake", 1065 | "mock", 1066 | "spy", 1067 | "stub" 1068 | ], 1069 | "support": { 1070 | "issues": "https://github.com/phpspec/prophecy/issues", 1071 | "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" 1072 | }, 1073 | "time": "2020-03-05T15:02:03+00:00" 1074 | }, 1075 | { 1076 | "name": "phpunit/php-code-coverage", 1077 | "version": "2.2.4", 1078 | "source": { 1079 | "type": "git", 1080 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 1081 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" 1082 | }, 1083 | "dist": { 1084 | "type": "zip", 1085 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", 1086 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", 1087 | "shasum": "" 1088 | }, 1089 | "require": { 1090 | "php": ">=5.3.3", 1091 | "phpunit/php-file-iterator": "~1.3", 1092 | "phpunit/php-text-template": "~1.2", 1093 | "phpunit/php-token-stream": "~1.3", 1094 | "sebastian/environment": "^1.3.2", 1095 | "sebastian/version": "~1.0" 1096 | }, 1097 | "require-dev": { 1098 | "ext-xdebug": ">=2.1.4", 1099 | "phpunit/phpunit": "~4" 1100 | }, 1101 | "suggest": { 1102 | "ext-dom": "*", 1103 | "ext-xdebug": ">=2.2.1", 1104 | "ext-xmlwriter": "*" 1105 | }, 1106 | "type": "library", 1107 | "extra": { 1108 | "branch-alias": { 1109 | "dev-master": "2.2.x-dev" 1110 | } 1111 | }, 1112 | "autoload": { 1113 | "classmap": [ 1114 | "src/" 1115 | ] 1116 | }, 1117 | "notification-url": "https://packagist.org/downloads/", 1118 | "license": [ 1119 | "BSD-3-Clause" 1120 | ], 1121 | "authors": [ 1122 | { 1123 | "name": "Sebastian Bergmann", 1124 | "email": "sb@sebastian-bergmann.de", 1125 | "role": "lead" 1126 | } 1127 | ], 1128 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1129 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1130 | "keywords": [ 1131 | "coverage", 1132 | "testing", 1133 | "xunit" 1134 | ], 1135 | "support": { 1136 | "irc": "irc://irc.freenode.net/phpunit", 1137 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 1138 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/2.2" 1139 | }, 1140 | "time": "2015-10-06T15:47:00+00:00" 1141 | }, 1142 | { 1143 | "name": "phpunit/php-file-iterator", 1144 | "version": "1.4.5", 1145 | "source": { 1146 | "type": "git", 1147 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1148 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" 1149 | }, 1150 | "dist": { 1151 | "type": "zip", 1152 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", 1153 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", 1154 | "shasum": "" 1155 | }, 1156 | "require": { 1157 | "php": ">=5.3.3" 1158 | }, 1159 | "type": "library", 1160 | "extra": { 1161 | "branch-alias": { 1162 | "dev-master": "1.4.x-dev" 1163 | } 1164 | }, 1165 | "autoload": { 1166 | "classmap": [ 1167 | "src/" 1168 | ] 1169 | }, 1170 | "notification-url": "https://packagist.org/downloads/", 1171 | "license": [ 1172 | "BSD-3-Clause" 1173 | ], 1174 | "authors": [ 1175 | { 1176 | "name": "Sebastian Bergmann", 1177 | "email": "sb@sebastian-bergmann.de", 1178 | "role": "lead" 1179 | } 1180 | ], 1181 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1182 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1183 | "keywords": [ 1184 | "filesystem", 1185 | "iterator" 1186 | ], 1187 | "support": { 1188 | "irc": "irc://irc.freenode.net/phpunit", 1189 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 1190 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" 1191 | }, 1192 | "time": "2017-11-27T13:52:08+00:00" 1193 | }, 1194 | { 1195 | "name": "phpunit/php-text-template", 1196 | "version": "1.2.1", 1197 | "source": { 1198 | "type": "git", 1199 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1200 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1201 | }, 1202 | "dist": { 1203 | "type": "zip", 1204 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1205 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1206 | "shasum": "" 1207 | }, 1208 | "require": { 1209 | "php": ">=5.3.3" 1210 | }, 1211 | "type": "library", 1212 | "autoload": { 1213 | "classmap": [ 1214 | "src/" 1215 | ] 1216 | }, 1217 | "notification-url": "https://packagist.org/downloads/", 1218 | "license": [ 1219 | "BSD-3-Clause" 1220 | ], 1221 | "authors": [ 1222 | { 1223 | "name": "Sebastian Bergmann", 1224 | "email": "sebastian@phpunit.de", 1225 | "role": "lead" 1226 | } 1227 | ], 1228 | "description": "Simple template engine.", 1229 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1230 | "keywords": [ 1231 | "template" 1232 | ], 1233 | "support": { 1234 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 1235 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" 1236 | }, 1237 | "time": "2015-06-21T13:50:34+00:00" 1238 | }, 1239 | { 1240 | "name": "phpunit/php-timer", 1241 | "version": "1.0.9", 1242 | "source": { 1243 | "type": "git", 1244 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1245 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 1246 | }, 1247 | "dist": { 1248 | "type": "zip", 1249 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 1250 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 1251 | "shasum": "" 1252 | }, 1253 | "require": { 1254 | "php": "^5.3.3 || ^7.0" 1255 | }, 1256 | "require-dev": { 1257 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 1258 | }, 1259 | "type": "library", 1260 | "extra": { 1261 | "branch-alias": { 1262 | "dev-master": "1.0-dev" 1263 | } 1264 | }, 1265 | "autoload": { 1266 | "classmap": [ 1267 | "src/" 1268 | ] 1269 | }, 1270 | "notification-url": "https://packagist.org/downloads/", 1271 | "license": [ 1272 | "BSD-3-Clause" 1273 | ], 1274 | "authors": [ 1275 | { 1276 | "name": "Sebastian Bergmann", 1277 | "email": "sb@sebastian-bergmann.de", 1278 | "role": "lead" 1279 | } 1280 | ], 1281 | "description": "Utility class for timing", 1282 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1283 | "keywords": [ 1284 | "timer" 1285 | ], 1286 | "support": { 1287 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 1288 | "source": "https://github.com/sebastianbergmann/php-timer/tree/master" 1289 | }, 1290 | "time": "2017-02-26T11:10:40+00:00" 1291 | }, 1292 | { 1293 | "name": "phpunit/php-token-stream", 1294 | "version": "1.4.12", 1295 | "source": { 1296 | "type": "git", 1297 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1298 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" 1299 | }, 1300 | "dist": { 1301 | "type": "zip", 1302 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", 1303 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", 1304 | "shasum": "" 1305 | }, 1306 | "require": { 1307 | "ext-tokenizer": "*", 1308 | "php": ">=5.3.3" 1309 | }, 1310 | "require-dev": { 1311 | "phpunit/phpunit": "~4.2" 1312 | }, 1313 | "type": "library", 1314 | "extra": { 1315 | "branch-alias": { 1316 | "dev-master": "1.4-dev" 1317 | } 1318 | }, 1319 | "autoload": { 1320 | "classmap": [ 1321 | "src/" 1322 | ] 1323 | }, 1324 | "notification-url": "https://packagist.org/downloads/", 1325 | "license": [ 1326 | "BSD-3-Clause" 1327 | ], 1328 | "authors": [ 1329 | { 1330 | "name": "Sebastian Bergmann", 1331 | "email": "sebastian@phpunit.de" 1332 | } 1333 | ], 1334 | "description": "Wrapper around PHP's tokenizer extension.", 1335 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1336 | "keywords": [ 1337 | "tokenizer" 1338 | ], 1339 | "support": { 1340 | "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", 1341 | "source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4" 1342 | }, 1343 | "abandoned": true, 1344 | "time": "2017-12-04T08:55:13+00:00" 1345 | }, 1346 | { 1347 | "name": "phpunit/phpunit-mock-objects", 1348 | "version": "2.3.8", 1349 | "source": { 1350 | "type": "git", 1351 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 1352 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" 1353 | }, 1354 | "dist": { 1355 | "type": "zip", 1356 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", 1357 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", 1358 | "shasum": "" 1359 | }, 1360 | "require": { 1361 | "doctrine/instantiator": "^1.0.2", 1362 | "php": ">=5.3.3", 1363 | "phpunit/php-text-template": "~1.2", 1364 | "sebastian/exporter": "~1.2" 1365 | }, 1366 | "require-dev": { 1367 | "phpunit/phpunit": "~4.4" 1368 | }, 1369 | "suggest": { 1370 | "ext-soap": "*" 1371 | }, 1372 | "type": "library", 1373 | "extra": { 1374 | "branch-alias": { 1375 | "dev-master": "2.3.x-dev" 1376 | } 1377 | }, 1378 | "autoload": { 1379 | "classmap": [ 1380 | "src/" 1381 | ] 1382 | }, 1383 | "notification-url": "https://packagist.org/downloads/", 1384 | "license": [ 1385 | "BSD-3-Clause" 1386 | ], 1387 | "authors": [ 1388 | { 1389 | "name": "Sebastian Bergmann", 1390 | "email": "sb@sebastian-bergmann.de", 1391 | "role": "lead" 1392 | } 1393 | ], 1394 | "description": "Mock Object library for PHPUnit", 1395 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 1396 | "keywords": [ 1397 | "mock", 1398 | "xunit" 1399 | ], 1400 | "support": { 1401 | "irc": "irc://irc.freenode.net/phpunit", 1402 | "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", 1403 | "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/2.3" 1404 | }, 1405 | "abandoned": true, 1406 | "time": "2015-10-02T06:51:40+00:00" 1407 | }, 1408 | { 1409 | "name": "sebastian/comparator", 1410 | "version": "1.2.4", 1411 | "source": { 1412 | "type": "git", 1413 | "url": "https://github.com/sebastianbergmann/comparator.git", 1414 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 1415 | }, 1416 | "dist": { 1417 | "type": "zip", 1418 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 1419 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 1420 | "shasum": "" 1421 | }, 1422 | "require": { 1423 | "php": ">=5.3.3", 1424 | "sebastian/diff": "~1.2", 1425 | "sebastian/exporter": "~1.2 || ~2.0" 1426 | }, 1427 | "require-dev": { 1428 | "phpunit/phpunit": "~4.4" 1429 | }, 1430 | "type": "library", 1431 | "extra": { 1432 | "branch-alias": { 1433 | "dev-master": "1.2.x-dev" 1434 | } 1435 | }, 1436 | "autoload": { 1437 | "classmap": [ 1438 | "src/" 1439 | ] 1440 | }, 1441 | "notification-url": "https://packagist.org/downloads/", 1442 | "license": [ 1443 | "BSD-3-Clause" 1444 | ], 1445 | "authors": [ 1446 | { 1447 | "name": "Jeff Welch", 1448 | "email": "whatthejeff@gmail.com" 1449 | }, 1450 | { 1451 | "name": "Volker Dusch", 1452 | "email": "github@wallbash.com" 1453 | }, 1454 | { 1455 | "name": "Bernhard Schussek", 1456 | "email": "bschussek@2bepublished.at" 1457 | }, 1458 | { 1459 | "name": "Sebastian Bergmann", 1460 | "email": "sebastian@phpunit.de" 1461 | } 1462 | ], 1463 | "description": "Provides the functionality to compare PHP values for equality", 1464 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1465 | "keywords": [ 1466 | "comparator", 1467 | "compare", 1468 | "equality" 1469 | ], 1470 | "support": { 1471 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1472 | "source": "https://github.com/sebastianbergmann/comparator/tree/1.2" 1473 | }, 1474 | "time": "2017-01-29T09:50:25+00:00" 1475 | }, 1476 | { 1477 | "name": "sebastian/diff", 1478 | "version": "1.4.3", 1479 | "source": { 1480 | "type": "git", 1481 | "url": "https://github.com/sebastianbergmann/diff.git", 1482 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 1483 | }, 1484 | "dist": { 1485 | "type": "zip", 1486 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 1487 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 1488 | "shasum": "" 1489 | }, 1490 | "require": { 1491 | "php": "^5.3.3 || ^7.0" 1492 | }, 1493 | "require-dev": { 1494 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 1495 | }, 1496 | "type": "library", 1497 | "extra": { 1498 | "branch-alias": { 1499 | "dev-master": "1.4-dev" 1500 | } 1501 | }, 1502 | "autoload": { 1503 | "classmap": [ 1504 | "src/" 1505 | ] 1506 | }, 1507 | "notification-url": "https://packagist.org/downloads/", 1508 | "license": [ 1509 | "BSD-3-Clause" 1510 | ], 1511 | "authors": [ 1512 | { 1513 | "name": "Kore Nordmann", 1514 | "email": "mail@kore-nordmann.de" 1515 | }, 1516 | { 1517 | "name": "Sebastian Bergmann", 1518 | "email": "sebastian@phpunit.de" 1519 | } 1520 | ], 1521 | "description": "Diff implementation", 1522 | "homepage": "https://github.com/sebastianbergmann/diff", 1523 | "keywords": [ 1524 | "diff" 1525 | ], 1526 | "support": { 1527 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1528 | "source": "https://github.com/sebastianbergmann/diff/tree/1.4" 1529 | }, 1530 | "time": "2017-05-22T07:24:03+00:00" 1531 | }, 1532 | { 1533 | "name": "sebastian/environment", 1534 | "version": "1.3.8", 1535 | "source": { 1536 | "type": "git", 1537 | "url": "https://github.com/sebastianbergmann/environment.git", 1538 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" 1539 | }, 1540 | "dist": { 1541 | "type": "zip", 1542 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", 1543 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", 1544 | "shasum": "" 1545 | }, 1546 | "require": { 1547 | "php": "^5.3.3 || ^7.0" 1548 | }, 1549 | "require-dev": { 1550 | "phpunit/phpunit": "^4.8 || ^5.0" 1551 | }, 1552 | "type": "library", 1553 | "extra": { 1554 | "branch-alias": { 1555 | "dev-master": "1.3.x-dev" 1556 | } 1557 | }, 1558 | "autoload": { 1559 | "classmap": [ 1560 | "src/" 1561 | ] 1562 | }, 1563 | "notification-url": "https://packagist.org/downloads/", 1564 | "license": [ 1565 | "BSD-3-Clause" 1566 | ], 1567 | "authors": [ 1568 | { 1569 | "name": "Sebastian Bergmann", 1570 | "email": "sebastian@phpunit.de" 1571 | } 1572 | ], 1573 | "description": "Provides functionality to handle HHVM/PHP environments", 1574 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1575 | "keywords": [ 1576 | "Xdebug", 1577 | "environment", 1578 | "hhvm" 1579 | ], 1580 | "support": { 1581 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1582 | "source": "https://github.com/sebastianbergmann/environment/tree/1.3" 1583 | }, 1584 | "time": "2016-08-18T05:49:44+00:00" 1585 | }, 1586 | { 1587 | "name": "sebastian/exporter", 1588 | "version": "1.2.2", 1589 | "source": { 1590 | "type": "git", 1591 | "url": "https://github.com/sebastianbergmann/exporter.git", 1592 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 1593 | }, 1594 | "dist": { 1595 | "type": "zip", 1596 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", 1597 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 1598 | "shasum": "" 1599 | }, 1600 | "require": { 1601 | "php": ">=5.3.3", 1602 | "sebastian/recursion-context": "~1.0" 1603 | }, 1604 | "require-dev": { 1605 | "ext-mbstring": "*", 1606 | "phpunit/phpunit": "~4.4" 1607 | }, 1608 | "type": "library", 1609 | "extra": { 1610 | "branch-alias": { 1611 | "dev-master": "1.3.x-dev" 1612 | } 1613 | }, 1614 | "autoload": { 1615 | "classmap": [ 1616 | "src/" 1617 | ] 1618 | }, 1619 | "notification-url": "https://packagist.org/downloads/", 1620 | "license": [ 1621 | "BSD-3-Clause" 1622 | ], 1623 | "authors": [ 1624 | { 1625 | "name": "Jeff Welch", 1626 | "email": "whatthejeff@gmail.com" 1627 | }, 1628 | { 1629 | "name": "Volker Dusch", 1630 | "email": "github@wallbash.com" 1631 | }, 1632 | { 1633 | "name": "Bernhard Schussek", 1634 | "email": "bschussek@2bepublished.at" 1635 | }, 1636 | { 1637 | "name": "Sebastian Bergmann", 1638 | "email": "sebastian@phpunit.de" 1639 | }, 1640 | { 1641 | "name": "Adam Harvey", 1642 | "email": "aharvey@php.net" 1643 | } 1644 | ], 1645 | "description": "Provides the functionality to export PHP variables for visualization", 1646 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1647 | "keywords": [ 1648 | "export", 1649 | "exporter" 1650 | ], 1651 | "support": { 1652 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1653 | "source": "https://github.com/sebastianbergmann/exporter/tree/master" 1654 | }, 1655 | "time": "2016-06-17T09:04:28+00:00" 1656 | }, 1657 | { 1658 | "name": "sebastian/global-state", 1659 | "version": "1.1.1", 1660 | "source": { 1661 | "type": "git", 1662 | "url": "https://github.com/sebastianbergmann/global-state.git", 1663 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1664 | }, 1665 | "dist": { 1666 | "type": "zip", 1667 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1668 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1669 | "shasum": "" 1670 | }, 1671 | "require": { 1672 | "php": ">=5.3.3" 1673 | }, 1674 | "require-dev": { 1675 | "phpunit/phpunit": "~4.2" 1676 | }, 1677 | "suggest": { 1678 | "ext-uopz": "*" 1679 | }, 1680 | "type": "library", 1681 | "extra": { 1682 | "branch-alias": { 1683 | "dev-master": "1.0-dev" 1684 | } 1685 | }, 1686 | "autoload": { 1687 | "classmap": [ 1688 | "src/" 1689 | ] 1690 | }, 1691 | "notification-url": "https://packagist.org/downloads/", 1692 | "license": [ 1693 | "BSD-3-Clause" 1694 | ], 1695 | "authors": [ 1696 | { 1697 | "name": "Sebastian Bergmann", 1698 | "email": "sebastian@phpunit.de" 1699 | } 1700 | ], 1701 | "description": "Snapshotting of global state", 1702 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1703 | "keywords": [ 1704 | "global state" 1705 | ], 1706 | "support": { 1707 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1708 | "source": "https://github.com/sebastianbergmann/global-state/tree/1.1.1" 1709 | }, 1710 | "time": "2015-10-12T03:26:01+00:00" 1711 | }, 1712 | { 1713 | "name": "sebastian/recursion-context", 1714 | "version": "1.0.5", 1715 | "source": { 1716 | "type": "git", 1717 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1718 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" 1719 | }, 1720 | "dist": { 1721 | "type": "zip", 1722 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 1723 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 1724 | "shasum": "" 1725 | }, 1726 | "require": { 1727 | "php": ">=5.3.3" 1728 | }, 1729 | "require-dev": { 1730 | "phpunit/phpunit": "~4.4" 1731 | }, 1732 | "type": "library", 1733 | "extra": { 1734 | "branch-alias": { 1735 | "dev-master": "1.0.x-dev" 1736 | } 1737 | }, 1738 | "autoload": { 1739 | "classmap": [ 1740 | "src/" 1741 | ] 1742 | }, 1743 | "notification-url": "https://packagist.org/downloads/", 1744 | "license": [ 1745 | "BSD-3-Clause" 1746 | ], 1747 | "authors": [ 1748 | { 1749 | "name": "Jeff Welch", 1750 | "email": "whatthejeff@gmail.com" 1751 | }, 1752 | { 1753 | "name": "Sebastian Bergmann", 1754 | "email": "sebastian@phpunit.de" 1755 | }, 1756 | { 1757 | "name": "Adam Harvey", 1758 | "email": "aharvey@php.net" 1759 | } 1760 | ], 1761 | "description": "Provides functionality to recursively process PHP variables", 1762 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1763 | "support": { 1764 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1765 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/master" 1766 | }, 1767 | "time": "2016-10-03T07:41:43+00:00" 1768 | }, 1769 | { 1770 | "name": "sebastian/version", 1771 | "version": "1.0.6", 1772 | "source": { 1773 | "type": "git", 1774 | "url": "https://github.com/sebastianbergmann/version.git", 1775 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 1776 | }, 1777 | "dist": { 1778 | "type": "zip", 1779 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1780 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1781 | "shasum": "" 1782 | }, 1783 | "type": "library", 1784 | "autoload": { 1785 | "classmap": [ 1786 | "src/" 1787 | ] 1788 | }, 1789 | "notification-url": "https://packagist.org/downloads/", 1790 | "license": [ 1791 | "BSD-3-Clause" 1792 | ], 1793 | "authors": [ 1794 | { 1795 | "name": "Sebastian Bergmann", 1796 | "email": "sebastian@phpunit.de", 1797 | "role": "lead" 1798 | } 1799 | ], 1800 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1801 | "homepage": "https://github.com/sebastianbergmann/version", 1802 | "support": { 1803 | "issues": "https://github.com/sebastianbergmann/version/issues", 1804 | "source": "https://github.com/sebastianbergmann/version/tree/1.0.6" 1805 | }, 1806 | "time": "2015-06-21T13:59:46+00:00" 1807 | }, 1808 | { 1809 | "name": "webmozart/assert", 1810 | "version": "1.9.1", 1811 | "source": { 1812 | "type": "git", 1813 | "url": "https://github.com/webmozarts/assert.git", 1814 | "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" 1815 | }, 1816 | "dist": { 1817 | "type": "zip", 1818 | "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", 1819 | "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", 1820 | "shasum": "" 1821 | }, 1822 | "require": { 1823 | "php": "^5.3.3 || ^7.0 || ^8.0", 1824 | "symfony/polyfill-ctype": "^1.8" 1825 | }, 1826 | "conflict": { 1827 | "phpstan/phpstan": "<0.12.20", 1828 | "vimeo/psalm": "<3.9.1" 1829 | }, 1830 | "require-dev": { 1831 | "phpunit/phpunit": "^4.8.36 || ^7.5.13" 1832 | }, 1833 | "type": "library", 1834 | "autoload": { 1835 | "psr-4": { 1836 | "Webmozart\\Assert\\": "src/" 1837 | } 1838 | }, 1839 | "notification-url": "https://packagist.org/downloads/", 1840 | "license": [ 1841 | "MIT" 1842 | ], 1843 | "authors": [ 1844 | { 1845 | "name": "Bernhard Schussek", 1846 | "email": "bschussek@gmail.com" 1847 | } 1848 | ], 1849 | "description": "Assertions to validate method input/output with nice error messages.", 1850 | "keywords": [ 1851 | "assert", 1852 | "check", 1853 | "validate" 1854 | ], 1855 | "support": { 1856 | "issues": "https://github.com/webmozarts/assert/issues", 1857 | "source": "https://github.com/webmozarts/assert/tree/1.9.1" 1858 | }, 1859 | "time": "2020-07-08T17:02:28+00:00" 1860 | } 1861 | ], 1862 | "aliases": [], 1863 | "minimum-stability": "stable", 1864 | "stability-flags": [], 1865 | "prefer-stable": false, 1866 | "prefer-lowest": false, 1867 | "platform": { 1868 | "ext-json": "*" 1869 | }, 1870 | "platform-dev": [], 1871 | "platform-overrides": { 1872 | "php": "5.6.0" 1873 | }, 1874 | "plugin-api-version": "2.6.0" 1875 | } 1876 | --------------------------------------------------------------------------------