Skip to content
This repository has been archived by the owner on Oct 19, 2021. It is now read-only.

Add support for JSON-LD #19

Open
lanthaler opened this issue Jun 18, 2014 · 3 comments
Open

Add support for JSON-LD #19

lanthaler opened this issue Jun 18, 2014 · 3 comments

Comments

@lanthaler
Copy link

Nice library. I'm wondering what it would take to add support for JSON-LD (which is btw. the only proper standard in this space at the moment) and whether support for it is planned. JSON-LD is a bit different than the formats you currently support as also the attribute names are linked to URLs in a so called context.

@plexus
Copy link
Owner

plexus commented Jun 18, 2014

Support for more formats is certainly welcome. I've written up a bit more info on what is expected to make that happen https://github.com/plexus/yaks/blob/master/ADDING_FORMATS.md

In the case of JSON-LD the main missing feature is RDF identifiers. For "@id" and "@type" the serializer could look for a self and profile link. As a first step to generate "@context" we could reuse the relation identifiers, something like this.

$yaks = Yaks.new do
  default_format :json_ld
  rel_template 'http://api.example.org/rel/{dest}'
end

class PostMapper < Yaks::Mapper
  link :self, 'http://api.example.com/post/{id}'
  link :profile, 'http://api.example.com/profiles/post'
  attributes :author, :date, :body
end

$yaks.serialize(post)
{
  "@context": {
    "author": "http://api.example.org/rel/author",
    "date": "http://api.example.org/rel/date",
    "body": "http://api.example.org/rel/body"
  },
  "@id": "http://api.example.com/post/9",
  "@type": "http://api.example.com/profiles/post",
  "author": "Arne",
  "date": "...",
  "body": "..."
}

Of course Link relations is not the same as RDF identifiers. The above also goes against the Yaks philosophy of being able to specify everything explicitly, and only deducing e.g. url's when not explicitly given. So maybe something like this

class PostMapper < Yaks::Mapper
  attribute :author, rdf_type: 'foaf:Person'
end

Maybe with a top-level fallback like

$yaks = Yaks.new do
  rdf_type_template 'http://api.example.com/vocabulary#{name}'
end

It would be a small effort to add basic JSON-LD support, however I think I'll first wait and see a bit until someone can come up with a PR, so I know somebody will also use it and help maintain it.

@plexus
Copy link
Owner

plexus commented Apr 19, 2015

I've given this a lot more thought recently, and I'd like to make this happen. Let me do a bit of a brain dump here of my current thoughts on this.

I think the only fruitful way to go about it is to rely on the RDF tools already available for Ruby, so we can map to an rdf graph, and have the existing tooling represent that as JSON-LD, RDFa, etc.

As a first step Yaks will have to become smarter about identifiers. Currently we have "rels" (RFC5988), which are either a Symbol (officially registered rel), or a String (custom rel using a URI). We'll have to add the ability to use objects as identifiers, that have to support specific protocols.

now:

link_to :self, "/foo"
link_to "http://example.com/rel/bar", "/bar/{id}"

future

link_to RDF::DC.title, "/foo/{id}/title"

In this case we're using an RDF::Vocabulary::Term, which responds to qname ([:dc, :title]), to_str ("http://purl.org/dc/terms/title"), to_term, etc. This allows a given format or context to use the representation it prefers. Similarly we could have Yaks::Vocabulary::Rel, which would implement to_term, if you want to treat it as an RDF vocabulary. (there are proposals for how to represent RFC5988 style keywords as URIs for use in RDF).

We would still support symbols as strings as we do now for conciseness and backwards compatibility, but once we arrive at Yaks::Resource these would be represented as objects, so each output format can represent how it sees most fit.

The end goal is to map attributes, links, and forms, all to RDF triplets. The "context" used in JSON-LD is, if I understand it correctly, just a way of compacting the graph, which can be handled by the existing RDF tooling.

We would still need a way to add type information for attributes. However one cool opportunity I see is generating base mapper classes based on existing schemas, which you can subclass to implement how certain values are pulled out of your objects.

# If the methods on your object already match the ones from the schema, you can simply use this
# out of the box. If not you can redefine them as shown below
class MusicEventMapper < Yaks::SchemaOrg::MusicEvent
  def start_date
    object.date
  end
end

This way we can encode all the type information based on the schema.

@gkellogg
Copy link

Let me know if you'd like some help in working with/understanding the Ruby RDF libraries (including JSON-LD).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants