diff --git a/pyproject.toml b/pyproject.toml index f2ecede..2762a42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "yaml-ld" -version = "1.1.16" +version = "1.1.17" description = "YAML-LD for Python" authors = ["Anatoly Scherbakov "] license = "MIT" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..0383177 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +max-imports = 15 diff --git a/yaml_ld/document_loaders/content_types.py b/yaml_ld/document_loaders/content_types.py index 32dced8..9fc4830 100644 --- a/yaml_ld/document_loaders/content_types.py +++ b/yaml_ld/document_loaders/content_types.py @@ -6,6 +6,7 @@ from yarl import URL from yaml_ld.document_parsers.base import BaseDocumentParser +from yaml_ld.document_parsers.json_parser import JSONDocumentParser from yaml_ld.document_parsers.rdf_xml_parser import RDFXMLParser from yaml_ld.document_parsers.turtle_parser import TurtleParser from yaml_ld.document_parsers.yaml_parser import YAMLDocumentParser @@ -95,8 +96,8 @@ def parser_by_content_type_map(): ) return { - 'application/json': YAMLDocumentParser, - APPLICATION_LD_JSON: YAMLDocumentParser, + 'application/json': JSONDocumentParser, + APPLICATION_LD_JSON: JSONDocumentParser, 'application/yaml': YAMLDocumentParser, 'application/x-yaml': YAMLDocumentParser, 'application/ld+yaml': YAMLDocumentParser, diff --git a/yaml_ld/document_parsers/json_parser.py b/yaml_ld/document_parsers/json_parser.py new file mode 100644 index 0000000..83e7642 --- /dev/null +++ b/yaml_ld/document_parsers/json_parser.py @@ -0,0 +1,44 @@ +import io +import json + +from yaml_ld.document_parsers.base import ( + BaseDocumentParser, + DocumentLoaderOptions, +) +from yaml_ld.errors import ( + DocumentIsScalar, + InvalidEncoding, + LoadingDocumentFailed, +) +from yaml_ld.models import JsonLdRecord + + +def ensure_not_scalar(document) -> JsonLdRecord | list[JsonLdRecord]: + """Ensure document is not a scalar value.""" + if not isinstance(document, (dict, list)): + raise DocumentIsScalar(document) + + return document + + +class JSONDocumentParser(BaseDocumentParser): + """Parse JSON and JSON-LD documents.""" + + def __call__( + self, + data_stream: io.BytesIO, + source: str, + options: DocumentLoaderOptions, + ) -> JsonLdRecord | list[JsonLdRecord]: + """Parse JSON document into LD.""" + try: + text = data_stream.read().decode('utf-8') + except UnicodeDecodeError as unicode_decode_error: + raise InvalidEncoding() from unicode_decode_error + + try: + document = json.loads(text) + except json.JSONDecodeError as json_error: + raise LoadingDocumentFailed(path=source) from json_error + + return ensure_not_scalar(document)