简体   繁体   中英

SHACL equivalent of JSON-Schema “uniqueItems”

So I'm tasked with converting a JSON-Schema describing an ontology to SHACL.

JSON-Schema has the uniqueItems construct, which, as the name suggests, forces all elements in an array to be unique. For my purposes, only elements of type String are considered.

Is there a similar construct in SHACL? sh:disjoint requires explicit unique paths so it doesn't apply. I'm considering creating a SPARQL constraint, though since my instances are all anonymous nodes, I haven't been able to get it to work yet.

Edit: Adding examples

Valid JSON:

{
                "name": "Robert Lewandowski",
                "mbox": "robert@bayern.de",
                "contributor_id": {
                    "identifier": "https://orcid.org/TEST",
                    "type": "orcid"
                },
                "role": [
                    "ContactPerson",
                    "DataManager"
                ]
            }

Invalid JSON:

{
                "name": "Robert Lewandowski",
                "mbox": "robert@bayern.de",
                "contributor_id": {
                    "identifier": "https://orcid.org/TEST",
                    "type": "orcid"
                },
                "role": [
                    "ContactPerson",
                    "ContactPerson"
                ]
            }

Valid TTL:

madmp:contributor [ foaf:mbox "robert@bayern.de" ;
                    foaf:name "Robert Lewandowski" ;
                    madmp:contributor_id  [ terms:identifier "https://orcid.org/TEST" ;
                                           madmp:identifier_type  "orcid"
                                          ] ;
                    madmp:role ( "ContactPerson" "DataManager")
                  ] ;

Invalid TTL:

madmp:contributor [ foaf:mbox "robert@bayern.de" ;
                    foaf:name "Robert Lewandowski" ;
                    madmp:contributor_id  [ terms:identifier "https://orcid.org/TEST" ;
                                           madmp:identifier_type  "orcid"
                                          ] ;
                    madmp:role ( "ContactPerson" "ContactPerson")
    

So this is a solution I came up with. It uses the dash vocabulary to first make sure the rdf:List structure is valid. The SPARQL constraint then makes sure that the values are unique.

It might not be pretty, but it works for me.

sh:property [
            sh:path madmp:role;
            sh:name "The Role Schema";
            sh:description "Type of contributor";
            sh:node dash:ListShape;
            sh:minCount 1 ;
            sh:property [
                sh:path ( [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ;
                sh:datatype xsd:string ;
                sh:minCount 1 ;
            ]
        ];
        sh:sparql [
            sh:message "Contributor {?name} has role {?role} more than once ({?roleCount} times).";
            sh:prefixes (madmp: rdf: foaf:);
            sh:select """
              PREFIX madmp: <https://w3id.org/madmp/terms#>
              PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
              prefix foaf:  <http://xmlns.com/foaf/0.1/>

              SELECT $this ?role ?name (COUNT(?role) AS ?roleCount)
              WHERE {
                  $this $PATH ?contributor.
                  ?contributor madmp:role/rdf:rest*/rdf:first ?role;
                  foaf:name ?name
              }
              GROUP BY $this ?name ?role
              HAVING (?roleCount > 1)
            """
        ]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM