piprate / json-gold

A JSON-LD processor for Go
Apache License 2.0
259 stars 30 forks source link

Turtle (TTL) RDF to JSON-LD to an Object #53

Closed BoraBak closed 2 years ago

BoraBak commented 3 years ago

Hello, my main goal is to convert .ttl file format to an object or a "simple" .json file format. For that, I'm converting the .ttl file to a json-ld. And from there, using the current repo, convert from json-ld to an object.


I tried 2 options in order to convert a .ttl file format to json-ld file format.

1) using github.com/deiu/rdf2go - worked

func convertTtlToJsonLd1() error {
    w, _ := os.OpenFile("data/hosts-ld.json", os.O_CREATE|os.O_WRONLY, 0644)
    r, _ := os.OpenFile("data/hosts.ttl", os.O_CREATE|os.O_RDONLY, 0664)
    g := rdf2go.NewGraph("baseUri")
    if err := g.Parse(r, "text/turtle"); err != nil {
        return err
    }
    return g.Serialize(w, "application/ld+json")
}

2) using github.com/piprate/json-gold/ld - didn't work: throwing the following error panic: runtime error: invalid memory address or nil pointer dereference

func convertTtlToJsonLd2() {
    f, err := ioutil.ReadFile("data/hosts-test.ttl")
    if err != nil {
        panic(err)
    }

    triples := string(f)

    proc := ld.NewJsonLdProcessor()
    options := ld.NewJsonLdOptions("")

    doc, err := proc.FromRDF(triples, options)
    if err != nil {
        panic(err)
    }

    ld.PrintDocument("JSON-LD output", doc)
}

I verified the conversion from TTL to json-ld in the following website: http://rdfvalidator.mybluemix.net/


Then, I tried to convert the json-ld to an object: The object I'm converting to is Host. Assume that both outputs from the above functions are writing to data/hosts-ld.json file.

func testJsonLd() {
    f, err := ioutil.ReadFile("data/hosts-ld.json")
    if err != nil {
        panic(err)
    }

    jsnLd := string(f)
    var p Host
    if err := jsonld.Unmarshal([]byte(jsnLd), &p); err != nil {
        log.Fatal(err)
    }

    fmt.Println(p)
}

hosts-test.ttl

@prefix ns3:    <http://xmlns.com/foaf/0.1/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix ns0:    <http://example.org/prop#> .

ns0:Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161
    a              ns0:Account ;
    ns0:GroupName  "Administrators" ;
    ns0:ID         "0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161" ;
    ns0:Privileges "SeRemoteInteractiveLogonRight" ;
    ns0:UserId     "161" ;
    ns0:Username   "administrator" .

ns0:Host_48d491d1-7998-59d6-b3ed-07a0868d7536_531
    a                                 ns0:Host ;
    ns0:Exploitable                   "XXE", "PEC";
    ns0:Account                       ns0:Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161 ;
    ns0:HostSignificance              "3" ;
    ns0:ID                            "48d491d1-7998-59d6-b3ed-07a0868d7536_531" .

ns0:Host
    a owl:Class .

ns0:Account
    a owl:ObjectProperty, owl:Class .

ns0:Exploitable
    a owl:DatatypeProperty .

ns0:GroupName
    a owl:DatatypeProperty .

ns0:HostSignificance
    a owl:DatatypeProperty .

ns0:ID
    a owl:DatatypeProperty .

ns0:IP
    a owl:DatatypeProperty .

ns0:LocalAccountTokenFilterPolicy
    a owl:DatatypeProperty .

ns0:LsaRunAsPPL
    a owl:DatatypeProperty .

ns0:Privileges
    a owl:DatatypeProperty .

ns0:UserId
    a owl:DatatypeProperty .

ns0:Username
    a owl:DatatypeProperty .

Below is the json-ld file from the function convertTtlToJsonLd1(). Note. the json-ld below is different from the outputs from the website: http://rdfvalidator.mybluemix.net/

[
  {
    "@id": "http://example.org/prop#HostSignificance",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#IP",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#UserId",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#GroupName",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#ID",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#LsaRunAsPPL",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Username",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Host_48d491d1-7998-59d6-b3ed-07a0868d7536_531",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://example.org/prop#Host"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Host_48d491d1-7998-59d6-b3ed-07a0868d7536_531",
    "http://example.org/prop#Account": [
      {
        "@id": "http://example.org/prop#Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Account",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#Class"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Host_48d491d1-7998-59d6-b3ed-07a0868d7536_531",
    "http://example.org/prop#Exploitable": [
      {
        "@value": "PEC"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Host_48d491d1-7998-59d6-b3ed-07a0868d7536_531",
    "http://example.org/prop#HostSignificance": [
      {
        "@value": "3"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Account",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#ObjectProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Exploitable",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Privileges",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161",
    "http://example.org/prop#UserId": [
      {
        "@value": "161"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161",
    "http://example.org/prop#Username": [
      {
        "@value": "administrator"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Host_48d491d1-7998-59d6-b3ed-07a0868d7536_531",
    "http://example.org/prop#Exploitable": [
      {
        "@value": "XXE"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161",
    "http://example.org/prop#Privileges": [
      {
        "@value": "SeRemoteInteractiveLogonRight"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Host_48d491d1-7998-59d6-b3ed-07a0868d7536_531",
    "http://example.org/prop#ID": [
      {
        "@value": "48d491d1-7998-59d6-b3ed-07a0868d7536_531"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Host",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#Class"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#LocalAccountTokenFilterPolicy",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://www.w3.org/2002/07/owl#DatatypeProperty"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161",
    "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [
      {
        "@id": "http://example.org/prop#Account"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161",
    "http://example.org/prop#GroupName": [
      {
        "@value": "Administrators"
      }
    ]
  },
  {
    "@id": "http://example.org/prop#Account_0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161",
    "http://example.org/prop#ID": [
      {
        "@value": "0abb0c18-9fb7-57f2-8bcd-2cb07ffbe865_161"
      }
    ]
  }
]

The Host struct:

type Host struct {
    ID               string    `jsonld:"http://example.org/prop#ID"`
    Account          []Account `jsonld:"http://example.org/prop#Account"`
    HostSignificance string    `jsonld:"http://example.org/prop#HostSignificance"`
    Exploitable      []string  `jsonld:"http://example.org/prop#Exploitable"`
}

type Account struct {
    ID         string   `jsonld:"http://example.org/prop#ID"`
    UserId     string   `jsonld:"http://example.org/prop#UserId"`
    Username   string   `jsonld:"http://example.org/prop#Username"`
    GroupName  []string `jsonld:"http://example.org/prop#GroupName"`
    Privileges []string `jsonld:"http://example.org/prop#Privileges"`
}
BoraBak commented 3 years ago

Maybe if someone can supply a code example of: TTL -> JSON-LD -> Object

BoraBak commented 3 years ago

After investigation of the current, it seems that there is no support to parse Turtle from string into an RDFDataset: https://github.com/piprate/json-gold/blob/33b90c4ca86c41ea5c28cfd1ea0a5fd314c91848/ld/serialize_turtle.go#L23 🤦‍♂️

Nevertheless, if someone could write what's the logical path a program should go through in order to achieve a conversion from a TTL file to a Golang structs?

kazarena commented 2 years ago

@BoraBak, apologies for neglecting your issue report. As you have identified, JSON-goLD doesn't support Turtle as either input or output format. At the time this library was created there was no readily available Turtle processing package in Go. Maybe it exists now. If you are aware of one, please let me know and I'll see if I can add support for Turtle. PRs are also welcome.