diff --git a/lib/pyld/jsonld.py b/lib/pyld/jsonld.py index 9361be77..8a710622 100644 --- a/lib/pyld/jsonld.py +++ b/lib/pyld/jsonld.py @@ -48,6 +48,15 @@ XSD_INTEGER = 'http://www.w3.org/2001/XMLSchema#integer' XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string' +# Derived datatypes from integer. +XSD_LONG = 'http://www.w3.org/2001/XMLSchema#long' +XSD_INT = 'http://www.w3.org/2001/XMLSchema#int' +XSD_INTEGER_DERIVED = ( + XSD_INTEGER, + XSD_LONG, + XSD_INT, +) + # RDF constants RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' RDF_LIST = RDF + 'List' @@ -3539,14 +3548,14 @@ def _rdf_to_object(self, o, use_native_types, rdf_direction): elif rval['@value'] == 'false': rval['@value'] = False elif _is_numeric(rval['@value']): - if type_ == XSD_INTEGER: + if type_ in XSD_INTEGER_DERIVED: if rval['@value'].isdigit(): rval['@value'] = int(rval['@value']) elif type_ == XSD_DOUBLE: rval['@value'] = float(rval['@value']) # do not add native type if type_ not in [ - XSD_BOOLEAN, XSD_INTEGER, XSD_DOUBLE, XSD_STRING]: + XSD_BOOLEAN, XSD_DOUBLE, XSD_STRING, *XSD_INTEGER_DERIVED]: rval['@type'] = type_ elif (rdf_direction == 'i18n-datatype' and type_.startswith('https://www.w3.org/ns/i18n#')): diff --git a/tests/test_xsd_integer_types.py b/tests/test_xsd_integer_types.py new file mode 100644 index 00000000..af2ce658 --- /dev/null +++ b/tests/test_xsd_integer_types.py @@ -0,0 +1,144 @@ +""" +Test cases for XSD integer-derived datatype constants (XSD_INT, XSD_LONG, XSD_INTEGER_DERIVED). + +These tests verify that the XSD integer type constants are correctly defined and +properly used during RDF to JSON-LD conversion with native type conversion. +""" + +from pyld import jsonld + + +import pytest + + +@pytest.mark.parametrize( + "data,context,frame,expected", + [ + [ + { + "int_max": {"@type": "xsd#int", "@value": "2147483647"}, + "int_min": {"@type": "xsd#int", "@value": "-2147483648"}, + "int_val": {"@type": "xsd#int", "@value": "789"}, + }, + { + "p_int_max": { + "@id": "int_max", + "@type": "xsd#int", + }, + "p_int_min": { + "@id": "int_min", + "@type": "xsd#int", + }, + "p_int_val": { + "@id": "int_val", + "@type": "xsd#int", + }, + }, + { + "p_int_max": {}, + "p_int_min": {}, + "p_int_val": {}, + }, + { + "p_int_max": "2147483647", + "p_int_min": "-2147483648", + "p_int_val": "789", + }, + ], + [ + {"integer": {"@type": "xsd#integer", "@value": "42"}}, + { + "p_integer": { + "@id": "integer", + "@type": "xsd#integer", + }, + }, + { + "p_integer": {}, + }, + { + "p_integer": "42", + }, + ], + [ + { + "long_max": {"@type": "xsd#long", "@value": "9223372036854775807"}, + "long_min": {"@type": "xsd#long", "@value": "-9223372036854775808"}, + "long_val": {"@type": "xsd#long", "@value": "456"}, + }, + { + "p_long_max": { + "@id": "long_max", + "@type": "xsd#long", + }, + "p_long_min": { + "@id": "long_min", + "@type": "xsd#long", + }, + "p_long_val": { + "@id": "long_val", + "@type": "xsd#long", + }, + }, + { + "p_long_max": {}, + "p_long_min": {}, + "p_long_val": {}, + }, + { + "p_long_max": "9223372036854775807", + "p_long_min": "-9223372036854775808", + "p_long_val": "456", + }, + ], + [ + {"zero": {"@type": "xsd#integer", "@value": "0"}}, + { + "p_zero": { + "@id": "zero", + "@type": "xsd#integer", + }, + }, + { + "p_zero": {}, + }, + { + "p_zero": "0", + }, + ], + ], +) +def test_frame_with_integer_types(data, context, frame, expected): + """ + Given: + A RDF dataset containing values with XSD integer-derived types. + When: + Framing RDF data with XSD integer-derived types. + Then: + The framed output should correctly represent the integer values + according to their XSD types. + """ + rdf = [ + { + "@context": { + "@vocab": "http://example.org/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + }, + **data, + } + ] + + framed = jsonld.frame( + rdf, + frame={ + "@context": { + "@vocab": "http://example.org/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + **context, + }, + **frame, + }, + ) + # Remove @context for comparison + framed.pop("@context") + assert expected == framed