diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 9cf5f17..85d1fb9 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -101,6 +101,22 @@ machine (for instance for :doc:`syntax highlighting in text editors file.yml:57:1: [error] trailing spaces (trailing-spaces) file.yml:60:3: [error] wrong indentation: expected 4 but found 2 (indentation) +Add the ``-f json`` arguments if you need an output formatted as JSON. +The output will then look like: + +:: + + [ + { + "path": "file.yml", + "line": 6, + "char": 2, + "description": "[warning] missing starting space in comment (comments)", + "severity": "warning" + } + ] + + If you have a custom linting configuration file (see :doc:`how to configure yamllint `), it can be passed to yamllint using the ``-c`` option: diff --git a/tests/test_cli.py b/tests/test_cli.py index 9b7801d..c978e7b 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -26,6 +26,7 @@ import shutil import sys import tempfile import unittest +import json from tests.common import build_temp_workspace @@ -608,3 +609,11 @@ class CommandLineTestCase(unittest.TestCase): '\n' % path) self.assertEqual( (ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, '')) + + def test_json_output(self): + path = os.path.join(self.wd, 'a.yaml') + + with RunContext(self) as ctx: + cli.run(('-f', 'json', path)) + print (ctx.stdout) + self.assertTrue(json.loads(ctx.stdout)) diff --git a/yamllint/cli.py b/yamllint/cli.py index 311d66c..4217f84 100644 --- a/yamllint/cli.py +++ b/yamllint/cli.py @@ -22,6 +22,7 @@ import locale import os import platform import sys +import json from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION from yamllint import linter @@ -85,10 +86,20 @@ class Format(object): line += ' \033[2m(%s)\033[0m' % problem.rule return line + @staticmethod + def json(problem, filename): + return { + "path": filename, + "line": problem.line, + "char": problem.column, + "description": problem.message, + "severity": problem.level, + } def show_problems(problems, file, args_format, no_warn): max_level = 0 first = True + problems_json = [] for problem in problems: max_level = max(max_level, PROBLEM_LEVELS[problem.level]) @@ -96,6 +107,8 @@ def show_problems(problems, file, args_format, no_warn): continue if args_format == 'parsable': print(Format.parsable(problem, file)) + elif args_format == 'json': + problems_json.append(Format.json(problem, file)) elif args_format == 'colored' or \ (args_format == 'auto' and supports_color()): if first: @@ -108,6 +121,9 @@ def show_problems(problems, file, args_format, no_warn): first = False print(Format.standard(problem, file)) + if args_format == 'json': + print(json.dumps(problems_json)) + if not first and args_format != 'parsable': print('') @@ -131,7 +147,7 @@ def run(argv=None): action='store', help='custom configuration (as YAML source)') parser.add_argument('-f', '--format', - choices=('parsable', 'standard', 'colored', 'auto'), + choices=('parsable', 'standard', 'colored', 'json', 'auto'), default='auto', help='format for parsing output') parser.add_argument('-s', '--strict', action='store_true',