Placeholders for JSON names within SMS2 script

We are trying to map the following JSON structure using SMS2

{
"847584": {
        "Type": "ABC",
        "Duration": 1290.0,
        "Id": "47d88f8a-30bd-4e56-b13b-758f7012e8e4"
    },
    "8945": {
        "Type": "DEC",
        "Id": "47d88f8a-30bd-4e56-b13b-758f7012e8e4",
        "SentimentScore": 50.0,

    }

The "main" names within the structure are assigend arbitrarily (e.g., "847584" and "8945); we are trying to get a binding based on the "Id" field as shown below. This works fine when pointing to a concrete key like "847584". All mapped values are included correctly. Of course, the values from the other section ("8945") are missing:

MAPPING
FROM JSON {
{
    
           "847584":  {
"PhraseId": "?id",
"Duration": "?duration",
"SentimentScore": "?sentiment"

            }
}

}

TO{
  ?phrase a :Phrase  ;
:has_sentiment ?sentiment ;
:has_duration ?duration .

} WHERE {
BIND(TEMPLATE("http://example.com/phrase/{id}") AS ?phrase)
}

Is there a way to use a placeholder for a JSON name, e.g.:

FROM JSON {
{
    
           "?MY_PLACEHOLDER":  {
"PhraseId": "?id",
"Duration": "?duration",
"SentimentScore": "?sentiment"

            }
}

I'm not sure of any way to do it in the mapping. (maybe someone else knows of a way) but if you're able to preprocess the json files you could break them out to separate json files based on ?MY_PLACEHOLDER and map those. You could do it with jq and something like the following

for f in `cat input.json | jq -r 'keys[]'` ; do
  cat input.json | jq ".$f" > $f.json
done

Your mapping looks exactly right with the exception that the names of the fields in the JSON do not match the names of the fields in your mappings (Id vs PhraseId, type isn't mapped, 847584 doesn't have a sentiment score, ABC and DEF have the same Id of 47d88f8a-30bd-4e56-b13b-758f7012e8e4).

If I touch these items up it works like I think you expect:

json $ cat placeholders.json 
{
   "847584":{
      "Type":"ABC",
      "Duration":1290.0,
      "PhraseId":"47d88f8a-30bd-4e56-b13b-ABC"
   },
   "8945":{
      "Type":"DEC",
      "PhraseId":"47d88f8a-30bd-4e56-b13b-DEC",
      "SentimentScore":50.0
   }
}

json $ cat placeholders.sms 
PREFIX : <example:>

MAPPING
FROM JSON {
  {
    "?MY_PLACEHOLDER":{
      "Type":"?type",
      "Duration":"?duration",
      "PhraseId":"?id",
      "SentimentScore":"?sentiment"
    }
  }
}
TO {
  ?phrase a :Phrase  ;
    :has_type ?type ;
    :has_duration ?duration ;
    :has_sentiment ?sentiment .
}
WHERE {
  BIND(TEMPLATE("http://example.com/phrase/{id}") AS ?phrase)
}

json $ sa db create -n json
Successfully created database 'json'.


json $ sa virtual import json placeholders.sms placeholders.json 
Import completed successfully in 00:00:00.072.

json $ s data export json
@prefix : <http://api.stardog.com/> .
@prefix stardog: <tag:stardog:api:> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<http://example.com/phrase/47d88f8a-30bd-4e56-b13b-ABC> a <example:Phrase> ;
   <example:has_duration> 1290.0 ;
   <example:has_type> "ABC" .
<http://example.com/phrase/47d88f8a-30bd-4e56-b13b-DEC> a <example:Phrase> ;
   <example:has_type> "DEC" ;
   <example:has_sentiment> 50.0 .
json $ 

If it is intended that multiple objects share the same Id, then you'll get a single node of type Phrase with properties pulled from each object with mapped values.

-Paul

I should add, you can use the ?MY_PLACEHOLDER in your mappings if needed:

TO {
  ?phrase a :Phrase  ;
    :has_type ?type ;
    :has_json_key ?MY_PLACEHOLDER;
    :has_duration ?duration ;
    :has_sentiment ?sentiment .
}

Yes, this is exactly what is intended. Multiple objects share the same ID ("PhraseID") and contribute with various and different values (eg., duration from one object and sentiment from another one) in order to build one "Phrase" node.

It is good to know that I can acutally use a variable for a JSON-key. Currently, the import does not work however when doing so.

Got it; the issue was related to another section of the more complex original file.

Great!

I did another test given your feedback and it appears to work with the still-simple-but-modified files:

json $ cat placeholders.json 
{
   "847584":{
      "Type":"ABC",
      "Duration":1290.0,
      "PhraseId":"47d88f8a-30bd-4e56-b13b-758f7012e8e4"
   },
   "8945":{
      "Type":"DEC",
      "PhraseId":"47d88f8a-30bd-4e56-b13b-758f7012e8e4",
      "SentimentScore":50.0
   },
   "1234":{
      "Type":"XYZ",
      "PhraseId":"47d88f8a-30bd-4e56-b13b-123456789abc",
      "SentimentScore":0.0
   }
}

json $ cat placeholders.sms 
PREFIX : <example:>

MAPPING
FROM JSON {
  {
    "?MY_PLACEHOLDER":{
      "Type":"?type",
      "Duration":"?duration",
      "PhraseId":"?id",
      "SentimentScore":"?sentiment"
    }
  }
}
TO{
  ?phrase a :Phrase  ;
    :has_type ?type ;
    :has_placeholder ?MY_PLACEHOLDER ;
    :has_duration ?duration ;
    :has_sentiment ?sentiment .
}
WHERE {
  BIND(TEMPLATE("http://example.com/phrase/{id}") AS ?phrase)
}

json $ sa virtual import json placeholders.sms placeholders.json 
Import completed successfully in 00:00:00.070.

json $ s data export json
@prefix : <http://api.stardog.com/> .
@prefix stardog: <tag:stardog:api:> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<http://example.com/phrase/47d88f8a-30bd-4e56-b13b-758f7012e8e4> a <example:Phrase> ;
   <example:has_duration> 1290.0 ;
   <example:has_type> "ABC" , "DEC" ;
   <example:has_sentiment> 50.0 ;
   <example:has_placeholder> "847584" , "8945" .
<http://example.com/phrase/47d88f8a-30bd-4e56-b13b-123456789abc> a <example:Phrase> ;
   <example:has_type> "XYZ" ;
   <example:has_sentiment> 0.0 ;
   <example:has_placeholder> "1234" .
json $ 

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.