![](/img/trans.png)
[英]JSON-LD serialization string without indentation, spaces or line breaks in RDF4J / Sesame
[英]RDF4j Shacl validation gives different results for Turtle and JSON-LD
我对 RDF4J SHACL 验证引擎有疑问。
这是我使用 shacl 规则和示例有效负载文件作为 TTL 输入的代码:
String SHAPES = "rules.ttl";
String DATA = "input.ttl";
ShaclSail shaclSail = new ShaclSail(new MemoryStore());
Repository repo = new SailRepository(shaclSail);
try (RepositoryConnection connection = repo.getConnection()) {
connection.begin();
connection.add(new StringReader(Files.readString(Path.of(SHAPES))), RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH);
connection.commit();
connection.begin();
connection.add(new StringReader(Files.readString(Path.of(DATA))), RDFFormat.TURTLE);
connection.commit();
connection.begin();
connection.clear(RDF4J.SHACL_SHAPE_GRAPH);
connection.commit();
} catch (Exception e) {
Throwable cause = e.getCause();
if (cause instanceof ValidationException) {
Model validationReportModel = ((ValidationException) cause).validationReportAsModel();
Rio.write(validationReportModel, System.out, RDFFormat.TURTLE);
}
}
shacl 规则文件如下所示:
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix shacl: <http://www.w3.org/ns/shacl#> .
<http://example.com/Property>
a owl:DatatypeProperty, rdf:Property .
<http://example.com/Class>
a owl:Class .
<http://example.com/ClassShape>
a <http://www.w3.org/ns/shacl#NodeShape> ;
shacl:property <http://example.com/PropertyShape> ;
shacl:targetClass <http://example.com/Class> .
<http://example.com/PropertyShape>
a shacl:PropertyShape ;
shacl:datatype xsd:integer ;
shacl:maxCount 1 ;
shacl:minCount 1 ;
shacl:path <http://example.com/Property> .
和输入文件:
<http://example.com/1>
a <http://example.com/Class> ;
<http://example.com/Property> "test" .
上面的代码片段返回正确的数据类型违规结果为<http://example.com/Property> "test".
不是规则中定义的 integer: shacl:datatype xsd:integer;
. 这是我所期望的行为。
但是当我使用完全相同的数据但采用 JSON-LD 格式时:
...
connection.add(new StringReader(Files.readString(Path.of(SHAPES))), RDFFormat.JSONLD, RDF4J.SHACL_SHAPE_GRAPH);
...
connection.add(new StringReader(Files.readString(Path.of(DATA))), RDFFormat.JSONLD);
...
使用此规则文件:
{
"@context": {
"id": "@id",
"type": "@type",
"datatype": {
"@id": "http://www.w3.org/ns/shacl#datatype",
"@type": "@id"
},
"path": {
"@id": "http://www.w3.org/ns/shacl#path",
"@type": "@id"
},
"class": {
"@id": "http://www.w3.org/ns/shacl#class",
"@type": "@id"
},
"property": {
"@id": "http://www.w3.org/ns/shacl#property",
"@type": "@id",
"@container": "@set"
},
"targetClass": {
"@id": "http://www.w3.org/ns/shacl#targetClass",
"@type": "@id"
},
"maxCount": "http://www.w3.org/ns/shacl#maxCount",
"minCount": "http://www.w3.org/ns/shacl#minCount",
"PropertyShape": "http://www.w3.org/ns/shacl#PropertyShape",
"Property": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
"NodeShape": "http://www.w3.org/ns/shacl#NodeShape",
"Class": "http://www.w3.org/2002/07/owl#Class",
"DatatypeProperty": "http://www.w3.org/2002/07/owl#DatatypeProperty"
},
"@graph": [
{
"id": "http://example.com/Property",
"type": [
"DatatypeProperty",
"Property"
]
},
{
"id": "http://example.com/Class",
"type": "Class"
},
{
"id": "http://example.com/ClassShape",
"type": "NodeShape",
"property": [
"http://example.com/PropertyShape"
],
"targetClass": "http://example.com/Class"
},
{
"id": "http://example.com/PropertyShape",
"type": "PropertyShape",
"datatype": "http://www.w3.org/2001/XMLSchema#integer",
"maxCount": 1,
"minCount": 1,
"path": "http://example.com/Property"
}
]
}
和内容文件:
{
"@context": {
"Class": "http://example.com/Class",
"property": {
"@id": "http://example.com/Property",
"@type": "http://www.w3.org/2001/XMLSchema#integer"
}
},
"@graph": {
"@type": "Class",
"@id": "http://example.com/1",
"property": "test"
}
}
我没有发现任何违规行为,这非常令人惊讶,因为其他 SHACL 引擎行 Apache Jena 或在线https://shacl.org/playground/正在返回正确的数据类型违规。
当我从 @context 中删除property
类型时,出现数据类型冲突:
"@type": "http://www.w3.org/2001/XMLSchema#integer"
或将property
更改为 ObjectProperty:
"property": {
"@id": "http://example.com/property1"
...
}
但是当我使用字符串而不是 integer 时,没有数据类型违规。
这是 RDF4J 中的错误还是预期的行为?
您正在观察的是 JSON-LD 中类型强制的影响。 似乎某些解析器(甚至是EasyRDF解析器)在接受类型化值时会执行额外的步骤,如果该类型是已知的数字类型 - 他们尝试将其解析为实际数字并使用 output 中的结果,而忽略原始词汇价值。 尝试解析"property": " 100.0 "
——它会在将其转换为 integer 之前修剪空格并删除.0
。
这种解析可能显然会失败,但解析器可能没有正确编写以适应这种情况,所以在 EasyRDF 的情况下,这是"property": "test"
的结果:
<http://example.com/1>
a <http://example.com/Class> ;
<http://example.com/Property> 0 .
我假设 SHACL Playground 使用的解析器更智能一些,可以将其视为以下内容:
<http://example.com/1>
a <http://example.com/Class> ;
<http://example.com/Property> "test"^^<http://www.w3.org/2001/XMLSchema#integer> .
请注意,这是您在 JSON-LD 中实际指定的内容:通过说属性的类型为xsd:integer
,如果您不使用值 ZA8CFDE6331BD59EB66AC96F891C ,它永远不会是字符串。 根据 SHACL 规则,结果不仅应该是无效的,而且在 RDFS 和 OWL 中也是矛盾的。
我没有明确的解决方案,因为我不知道 RDF4J JSON-LD 解析器是否可以配置为表现不同。 但是,这些是我能想到的选项:
"@type": "http://www.w3.org/2001/XMLSchema#integer"
。 JSON-LD 的生产者必须明确说明值的类型,甚至像"10"
这样的东西也不会通过——它必须是10
作为 JSON 中的数字。 这仍然可以通过值 object (使用@type
)来规避。RDFFormat.JSONLD
或使用不同的解析器。http://example.com/Property
在 SHACL 中为非零,假设 0 确实是出现在那里的值。 旁注:SHACL Playground 使用的 JSON-LD 解析器绝对不是完美的,因为它还将"10.5"
或"10whatever"
解析为10
。 似乎它使用 JavaScript 的parseInt
或类似的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.