New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hierarchical JSON-LD writer #1049

Closed
yasengmarinov opened this Issue Jul 3, 2018 · 3 comments

Comments

Projects
None yet
3 participants
@yasengmarinov

yasengmarinov commented Jul 3, 2018

The current JSON-LD writer can only represent the JSON-LDs triple by triple. The idea behind this enhancement is to be able to represent the JSON-LD objects in a tree-like hierarchical view. Example:
Let's take for example the following 2 tuples:

<sch:node1> <sch:pred> <sch:node2> .
<sch:node2> <sch:pred2> <sch:node3> .

Output from current JSON-LD writer:

[ {
  "@id" : "sch:node1",
  "sch:pred" : [ {
    "@id" : "sch:node2"
  } ]
}, {
  "@id" : "sch:node2",
  "sch:pred2" : [ {
    "@id" : "sch:node3"
  } ]
} ]

Same output from hierarchical JSON-LD writer:

[ {
  "@id" : "sch:node1",
  "sch:pred" : [ {
    "@id" : "sch:node2",
    "sch:pred2" : [ {
      "@id" : "sch:node3"
    } ]
  } ]
} ]

This mode should work with the existing JSON-LD modes - like COMPACT, EXPAND, etc.
The benefit of this mode will be a JSON-LD object which is more human-readable.

yasengmarinov pushed a commit to yasengmarinov/rdf4j that referenced this issue Jul 3, 2018

Yasen Marinov
features/eclipse#1049 Introduce hierarchical JSON-LD representation b…
…y the JSONLDWriter

Signed-off-by: Yasen Marinov <yasen.marinov@ontotext.com>

@jeenbroekstra jeenbroekstra modified the milestones: 2.5.0, 2.4.0 Jul 9, 2018

yasengmarinov pushed a commit to yasengmarinov/rdf4j that referenced this issue Jul 9, 2018

Yasen Marinov
features/eclipse#1049 Add copyright header to new files
Signed-off-by: Yasen Marinov <yasen.marinov@ontotext.com>

jeenbroekstra added a commit that referenced this issue Jul 13, 2018

Merge pull request #1050 from yasengmarinov/features/#1049_Hierarchic…
…al_JSON_LD_writer

features/#1049 Introduce hierarchical JSON-LD representation by the J…
@RavinderSinghMaan

This comment has been minimized.

Contributor

RavinderSinghMaan commented Jul 24, 2018

@jeenbroekstra @yasengmarinov isn't this same as JSON-LD Framing https://json-ld.org/spec/latest/json-ld-framing/ with embed always?

@yasengmarinov

This comment has been minimized.

yasengmarinov commented Jul 26, 2018

Hi @RavinderSinghMaan ,
Indeed both functionalities look pretty similar. However, the Framing is much more for describing a resource while the hierarchical view is for presenting the whole JSON-LD. Its purpose is to provide a light-weight representation of the whole JSON-LD no matter what data it contains.
Frames are pretty cool but in order to be useful you need to know what resource do you want to display and in that case you should accept that some of the data in the JSON-LD file will not be included in the framed JSON-LD. Example:
This is the output for a given model from the hierarchical view:

[ {
  "@id" : "sch:node1",
  "@type" : [ "sch:type1" ],
  "sch:pred" : [ {
    "@id" : "sch:node2",
    "sch:pred" : [ {
      "@id" : "sch:node3",
      "sch:pred" : [ {
        "@id" : "sch:node4",
        "sch:pred" : [ {
          "@id" : "sch:node5",
          "sch:pred" : [ {
            "@id" : "sch:node6"
          } ]
        } ]
      } ]
    } ]
  } ]
}, {
  "@id" : "sch:node7",
  "sch:pred" : [ {
    "@id" : "sch:node6"
  } ]
} ]

If you want to display the same object with a frame (without knowing what type of node you are describing) you could use a frame like this:

{
  "@embed": "@always"
}

The result would be the following:

[ {
  "@id" : "sch:node1",
  "@type" : [ "sch:type1" ],
  "sch:pred" : [ {
    "@id" : "sch:node2",
    "sch:pred" : [ {
      "@id" : "sch:node3",
      "sch:pred" : [ {
        "@id" : "sch:node4",
        "sch:pred" : [ {
          "@id" : "sch:node5",
          "sch:pred" : [ {
            "@id" : "sch:node6"
          } ]
        } ]
      } ]
    } ]
  } ]
}, {
  "@id" : "sch:node2",
  "sch:pred" : [ {
    "@id" : "sch:node3",
    "sch:pred" : [ {
      "@id" : "sch:node4",
      "sch:pred" : [ {
        "@id" : "sch:node5",
        "sch:pred" : [ {
          "@id" : "sch:node6"
        } ]
      } ]
    } ]
  } ]
}, {
  "@id" : "sch:node3",
  "sch:pred" : [ {
    "@id" : "sch:node4",
    "sch:pred" : [ {
      "@id" : "sch:node5",
      "sch:pred" : [ {
        "@id" : "sch:node6"
      } ]
    } ]
  } ]
}, {
  "@id" : "sch:node4",
  "sch:pred" : [ {
    "@id" : "sch:node5",
    "sch:pred" : [ {
      "@id" : "sch:node6"
    } ]
  } ]
}, {
  "@id" : "sch:node5",
  "sch:pred" : [ {
    "@id" : "sch:node6"
  } ]
}, {
  "@id" : "sch:node7",
  "sch:pred" : [ {
    "@id" : "sch:node6"
  } ]
} ]

And this becomes practically unusable for describing big and complex objects. So you could restrict the frame to match a certain type like this:

{
  "@embed": "@always",
  "@type": "sch:type1"
}

The result would be:

[ {
  "@id" : "sch:node1",
  "@type" : [ "sch:type1" ],
  "sch:pred" : [ {
    "@id" : "sch:node2",
    "sch:pred" : [ {
      "@id" : "sch:node3",
      "sch:pred" : [ {
        "@id" : "sch:node4",
        "sch:pred" : [ {
          "@id" : "sch:node5",
          "sch:pred" : [ {
            "@id" : "sch:node6"
          } ]
        } ]
      } ]
    } ]
  } ]
} ]

But here we have lost some of the data of the original object - sch:node7 is missing because it is not with type sch:type1.
So the point of the hierarchical view is not to replace the framing, they just serve different purposes. The use-case for which it was created was "I want the results of SPARQL queries to be returned as a JSON-LD with hierarchy in order to be displayed to the users"

@RavinderSinghMaan

This comment has been minimized.

Contributor

RavinderSinghMaan commented Jul 27, 2018

@yasengmarinov Thanks for the explanation. Actually, the reason I asked this question was that I did something similar. But I extended the method so that it takes starting nodes of graphs. In our use case we needed to return top level resources along with linked resources but embed only once. Using framing one could use embed last option but the problem with type can be still there. So I added optional param which contain list of root node and then hierarchical view will put those node as top level nodes. To make it clear let us say we have below model

<sch:node1> <sch:pred> <sch:node2> .
<sch:node1> <sch:pred1> "Node1" .

<sch:node2> <sch:pred> <sch:node3> .
<sch:node2> <sch:pred1> "Node2" .

<sch:node3> <sch:pred> <sch:node2> .
<sch:node3> <sch:pred1> "Node3" .

<sch:node4> <sch:pred> <sch:node1> .
<sch:node4> <sch:pred1> "Node4" .

Signature of the interface method

String serialise(Model model, List<Resource> topLevelNodes)    

Then if topLevelNodes list contains sch:node1, sch:node3 serialisation will be

[ {
  "@id" : "sch:node1",
  "sch:pred1" : "Node1",
  "sch:pred" : [ {
    "@id" : "sch:node2",
    "sch:pred1" : "Node2",
    "sch:pred" : [ {
      "@id" : "sch:node3",
     } ]
} ,
{
  "@id" : "sch:node3",
    "sch:pred1" : "Node3",
  "sch:pred" : [ {
    "@id" : "sch:node2"
} ,

]

As you can see sch:node4 is missing. For our use case it never happens but we can provide different options i.e. thror Error , ignore it silently or serialise it as top node.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment