def parse_json(content, validator=None): assert isinstance(content, (str, bytes)) if isinstance(content, bytes): content = content.decode('utf-8', 'ignore') if not content.strip(): marker = Marker(0, '') raise ParseError('No content.', marker=marker, base_format='json') try: token = None if validator is None else tokenize_json(content) data = json.loads(content) except json.decoder.JSONDecodeError as exc: message = exc.msg + '.' marker = Marker(exc.pos, content) raise ParseError(message, marker=marker, base_format='json') from None if validator is None: return data try: return validator.validate(data) except ValidationError as exc: exc.set_error_context(token, content) raise exc
def parse_yaml(content, validator=None): assert isinstance(content, (str, bytes)) if isinstance(content, bytes): content = content.decode('utf-8', 'ignore') if not content.strip(): marker = Marker(0, '') raise ParseError('No content.', marker=marker, base_format='yaml') try: token = None if validator is None else tokenize_yaml(content) data = yaml.safe_load(content) except (yaml.scanner.ScannerError, yaml.parser.ParserError) as exc: position = getattr(exc, 'index', 0) marker = Marker(position, content) message = exc.problem raise ParseError(message, marker=marker, base_format='yaml') from None if validator is None: return data try: return validator.validate(data) except ValidationError as exc: exc.set_error_context(token, content) raise exc
def test_invalid_properties(): with pytest.raises(ValidationError) as exc: parse_json('{"a": "abc", "b": 123}', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ ErrorMessage('Must be a number.', Marker(6)), ErrorMessage('Invalid property name.', Marker(13)) ] assert error_messages == expecting
def test_invalid_top_level_item(): with pytest.raises(ValidationError) as exc: parse_json('123', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ErrorMessage('Must be an object.', Marker(0))] assert error_messages == expecting
def test_invalid_token(): with pytest.raises(ParseError) as exc: parse_json('-', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ErrorMessage("Expecting value.", Marker(0))] assert error_messages == expecting
def test_object_unterminated_after_value(): with pytest.raises(ParseError) as exc: parse_json('{"abc": "def"', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ErrorMessage("Expecting ',' delimiter.", Marker(13))] assert error_messages == expecting
def test_object_unterminated_after_key(): with pytest.raises(ParseError) as exc: parse_json('{"abc": ', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ErrorMessage("Expecting value.", Marker(8))] assert error_messages == expecting
def test_object_missing_comma_delimiter(): with pytest.raises(ParseError) as exc: parse_json('{"abc": "def" 1', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ErrorMessage("Expecting ',' delimiter.", Marker(14))] assert error_messages == expecting
def test_empty_string(): with pytest.raises(ParseError) as exc: parse_json(b'', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ErrorMessage('No content.', Marker(0))] assert error_messages == expecting
def test_object_invalid_property_name(): with pytest.raises(ParseError) as exc: parse_json('{"abc": "def", 1', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ ErrorMessage("Expecting property name enclosed in double quotes.", Marker(15)) ] assert error_messages == expecting
def test_object_missing_property_name(): with pytest.raises(ParseError) as exc: parse_json('{', VALIDATOR) error_messages = exc.value.get_error_messages() expecting = [ ErrorMessage('Expecting property name enclosed in double quotes.', Marker(1)) ] assert error_messages == expecting
def infer_json_or_yaml(content): assert isinstance(content, (str, bytes)) if isinstance(content, bytes): content = content.decode('utf-8', 'ignore') content = content.strip() if not content: marker = Marker(0, '') raise ParseError('No content.', marker=marker) return 'json' if content[0] in '{[' else 'yaml'