JSON-LD and
  MongoDB
Powering Linked Web Apps



    Gregg Kellogg
  gregg@greggkellogg.net
        @gkellogg
JSON-LD and Mongo

• JSON-LD – graph expression in JSON
• MongoDB – easily query JSON documents
• Together – efficient graph query optimized
  for client-side processing
Use Case
• WebApps: Single Page Applications (SPAS)
  • Use JSON as native object representation
  • REST access to web service mirroring
    objects
  • MongoDB document store maintaining
    equivalent object representations
• Data is linked, internally and externally (RDF)
JSON-LD
                                         @graph
   @context
                         @id

    JSON-based syntax to express linked data

                                        @language
        @value

                               @list
                                       @vocab
@type             @set
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],
    "name": "Call of Duty: Black Ops",
    "publisher": [
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",                  Context defines terms
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],
    "name": "Call of Duty: Black Ops",
    "publisher": [
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",                  Context defines terms
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",                            Identifier treated as IRI
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],
    "name": "Call of Duty: Black Ops",
    "publisher": [
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",                  Context defines terms
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",                            Identifier treated as IRI
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",                   Type same as rdf:type
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],
    "name": "Call of Duty: Black Ops",
    "publisher": [
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",                  Context defines terms
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",                            Identifier treated as IRI
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",                   Type same as rdf:type
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],                                                       Data-typed values
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],
    "name": "Call of Duty: Black Ops",
    "publisher": [
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",                  Context defines terms
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",                            Identifier treated as IRI
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",                   Type same as rdf:type
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],                                                       Data-typed values
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],                      Simple string values
    "name": "Call of Duty: Black Ops",
    "publisher": [
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",                    Context defines terms
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",                              Identifier treated as IRI
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",                      Type same as rdf:type
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],                                                         Data-typed values
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],                        Simple string values
    "name": "Call of Duty: Black Ops",
    "publisher": [                                         (unordered) arrays of values
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",                          Context defines terms
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",                                    Identifier treated as IRI
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",                            Type same as rdf:type
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],                                                                Data-typed values
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],                               Simple string values
    "name": "Call of Duty: Black Ops",
    "publisher": [                                               (unordered) arrays of values
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],                                                     subject reference links to other resources
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON, as expected
{
    "@context": "/contexts/wikia.jsonld",                          Context defines terms
    "@id": "500f1a1b6e7f1827ba000001",
    "@type": "wikia:VideoGame",                                    Identifier treated as IRI
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",
       "PEGI: 18+ (DS version is 16+) ",                            Type same as rdf:type
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],                                                                Data-typed values
    "datePublished": "2011-11-09",
    "description": "Primary game entry point",
    "genre": ["First-person shooter"],                               Simple string values
    "name": "Call of Duty: Black Ops",
    "publisher": [                                               (unordered) arrays of values
       {"@id": "501067246e7f184553000001"},
       {"@id": "5010675a6e7f18464d000001"}
    ],                                                     subject reference links to other resources
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",                           Arrays may be ordered in @context
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
JSON-LD context
{
    "@context": "/contexts/wikia.jsonld",                  {
    "@id": "500f1a1b6e7f1827ba000001",                         "@context": {
    "@type": "wikia:VideoGame",                                 "wikia":     "http://data.wikia.com/terms#",
    "contentRating": [                                          "xsd":      "http://www.w3.org/2001/XMLSchema#",
       "ESRB: Mature (DS version is Teen)",                     "@vocab":      "http://schema.org/",
       "PEGI: 18+ (DS version is 16+) ",                        "@language": "en",
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"
    ],                                                             "dateCreated": {"@type": "xsd:dateTime"},
    "datePublished": "2011-11-09",                                 "dateModified": {"@type": "xsd:dateTime"},
    "description": "Primary game entry point",                     "event":       {"@id": "wikia:event",
    "genre": ["First-person shooter"],                                             "@type": "@id",
    "name": "Call of Duty: Black Ops",                                             "@container": "@list"},
    "publisher": [                                                 "startDate":   {"@type": "xsd:dateTime"},
       {"@id": "501067246e7f184553000001"},                        "width":       {"@type": "xsd:integer"}
       {"@id": "5010675a6e7f18464d000001"}                     }
    ],                                                     }
    "event": [
       "500f28856e7f187196000001",
       "500f44556e7f18f7ef000001",
       "500f449e6e7f18f94b000001",
       "500f44e26e7f18fa75000001"
    ],
    "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"]
}
Syntactic Conventions

• Keys represent unique properties
• Values may be singular or multiple
 • May use strings for most value
    representations, with typing information
    maintained in a context.
Unique properties
                 {
Expanded Form:       "http://schema.org/publisher": [
                       {"@id": "501067246e7f184553000001"},
                       {"@id": "5010675a6e7f18464d000001"}
                     ]
                 }


                 {

Compact Form:        "publisher": [
                       "501067246e7f184553000001",
                       "5010675a6e7f18464d000001"
                     ]
                 }
Context:
                 {
                     "@context": {
                       "@vocab": "http://schema.org/",
                       "publisher":{"@type": "@id"},
                       ...
                     }
                 }
Language tagged values
                 {
Expanded Form:       "http://schema.org/name": {
                       "@value": "Call of Duty: Black Ops",
                       "@language": "en"
                     }
                 }




Compact Form:    { "name": "Call of Duty: Black Ops" }




Context:         {
                     "@context": {
                       "@vocab": "http://schema.org/",
                       "@language": "en",
                       ...
                     }
                 }
Typed values
                 {
Expanded Form:       "http://schema.org/datePublished": {
                       "@value": "2011-11-09",
                       "@type": "xsd:dateTime"
                     }
                 }




Compact Form:    { "datePublished": "2011-11-09" }



                 {
Context:             "@context": {
                       "@vocab": "http://schema.org/",
                       "xsd": "http://www.w3.org/2001/XMLSchema#",
                       "datePublished":{"@type": "xsd:dateTime"},
                       ...
                     }
                 }
Subject references
                 {
Expanded Form:       "http://schema.org/publisher": [
                       {"@id": "501067246e7f184553000001"},
                       {"@id": "5010675a6e7f18464d000001"}
                     ]
                 }


                 {

Compact Form:        "publisher": [
                       "501067246e7f184553000001",
                       "5010675a6e7f18464d000001"
                     ]
                 }
Context:
                 {
                     "@context": {
                       "@vocab": "http://schema.org/",
                       "publisher":{"@type": "@id"},
                       ...
                     }
                 }
Nesting
     Flattened Form                                                    Nested Form:
{                                                               {
    "@context": "/contexts/wikia.jsonld",                           "@context": "/contexts/wikia.jsonld",
    "@graph": [                                                     "@id": "500f1a1b6e7f1827ba000001",
      {                                                             "@type": "wikia:VideoGame",
        "@id": "500f1a1b6e7f1827ba000001",                          "name": "Call of Duty: Black Ops",
        "@type": "wikia:VideoGame",                                 "publisher": [
        "name": "Call of Duty: Black Ops",                            {
        "publisher": [                                                  "@id": "501067246e7f184553000001",
           "501067246e7f184553000001",                                  "name": "Activision",
           "5010675a6e7f18464d000001"                                   "url": "http://callofduty.wikia.com/wiki/Activision",
        ]                                                               "@type": "schema:Corporation"
      }, {                                                            }, {
        "@id": "501067246e7f184553000001",                              "@id": "5010675a6e7f18464d000001",
        "name": "Activision",                                           "@type": "schema:Corporation",
        "url": "http://callofduty.wikia.com/wiki/Activision",           "name": "Square Enix (Japan)"
        "@type": "schema:Corporation"                                 }
      }, {                                                          ]
        "@id": "5010675a6e7f18464d000001",                      }
        "@type": "schema:Corporation",
        "name": "Square Enix (Japan)"
      }
    ]
}
Nesting
     Flattened Form                                                    Nested Form:
{                                                               {
    "@context": "/contexts/wikia.jsonld",                           "@context": "/contexts/wikia.jsonld",
    "@graph": [                                                     "@id": "500f1a1b6e7f1827ba000001",
      {                                                             "@type": "wikia:VideoGame",
        "@id": "500f1a1b6e7f1827ba000001",                          "name": "Call of Duty: Black Ops",
        "@type": "wikia:VideoGame",                                 "publisher": [
        "name": "Call of Duty: Black Ops",                            {
        "publisher": [                                                  "@id": "501067246e7f184553000001",
           "501067246e7f184553000001",                                  "name": "Activision",
           "5010675a6e7f18464d000001"                                   "url": "http://callofduty.wikia.com/wiki/Activision",
        ]                                                               "@type": "schema:Corporation"
      }, {                                                            }, {
        "@id": "501067246e7f184553000001",                              "@id": "5010675a6e7f18464d000001",
        "name": "Activision",                                           "@type": "schema:Corporation",
        "url": "http://callofduty.wikia.com/wiki/Activision",           "name": "Square Enix (Japan)"
        "@type": "schema:Corporation"                                 }
      }, {                                                          ]
        "@id": "5010675a6e7f18464d000001",                      }
        "@type": "schema:Corporation",
        "name": "Square Enix (Japan)"
      }
    ]
}
Nesting
     Flattened Form                                                    Nested Form:
{                                                               {
    "@context": "/contexts/wikia.jsonld",                           "@context": "/contexts/wikia.jsonld",
    "@graph": [                                                     "@id": "500f1a1b6e7f1827ba000001",
      {                                                             "@type": "wikia:VideoGame",
        "@id": "500f1a1b6e7f1827ba000001",                          "name": "Call of Duty: Black Ops",
        "@type": "wikia:VideoGame",                                 "publisher": [
        "name": "Call of Duty: Black Ops",                            {
        "publisher": [                                                  "@id": "501067246e7f184553000001",
           "501067246e7f184553000001",                                  "name": "Activision",
           "5010675a6e7f18464d000001"                                   "url": "http://callofduty.wikia.com/wiki/Activision",
        ]                                                               "@type": "schema:Corporation"
      }, {                                                            }, {
        "@id": "501067246e7f184553000001",                              "@id": "5010675a6e7f18464d000001",
        "name": "Activision",                                           "@type": "schema:Corporation",
        "url": "http://callofduty.wikia.com/wiki/Activision",           "name": "Square Enix (Japan)"
        "@type": "schema:Corporation"                                 }
      }, {                                                          ]
        "@id": "5010675a6e7f18464d000001",                      }
        "@type": "schema:Corporation",
        "name": "Square Enix (Japan)"
      }
    ]
}
In-memory linking
     Flattened Form                                 Linked Form:
{
     "@id": "500f1a1b6e7f1827ba000001",          @id         500f1a1b6e7f1827ba000001
     "type": "wikia:VideoGame",
     "schema:name": "Call of Duty: Black Ops",   type        wikia:VideoGame
     "wikia:event": [
       {"@id": "500f28856e7f187196000001"},      name        "Call of Duty: Black Ops"
       {"@id": "500f44556e7f18f7ef000001"},      event       500f28856e7f187196000001
       {"@id": "500f449e6e7f18f94b000001"},
       {"@id": "500f44e26e7f18fa75000001"}
     ]
},
{                                                @id         500f28856e7f187196000001
     "@id": "500f28856e7f187196000001",
                                                 type        cod:Mission
     "type": "cod:Mission",
     "schema:name": "Operation 40",              name        "Operation 40"
     "schema:startDate": "1961-04-17",           startDate   "1961-04-17"
     "wikia:eventIn": [
       {"@id": "500f1a1b6e7f1827ba000001"}       event       500f1a1b6e7f1827ba000001
     ]
}
Turtle Mapping
{                                                        @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    "@context": "/contexts/wikia.jsonld",                @prefix schema: <http://schema.org/> .
    "@id": "500f1a1b6e7f1827ba000001",                   @prefix wikia: <http://data.wikia.com/terms#> .
    "@type": "wikia:VideoGame",                          @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
    "contentRating": [
       "ESRB: Mature (DS version is Teen)",              <500f1a1b6e7f1827ba000001> a wikia:VideoGame;
       "PEGI: 18+ (DS version is 16+) ",                    schema:contentRating "ESRB: Mature (DS version is Teen)"@en,
       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"       "PEGI: 18+ (DS version is 16+) "@en,
    ],                                                       "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"@en;
    "datePublished": "2011-11-09",                          schema:datePublished: "2011-11-09"^^xsd:dateTime;
    "name": "Call of Duty: Black Ops",                      schema:name "Call of Duty: Black Ops"@en;
    "publisher": [                                          schema:publisher <501067246e7f184553000001>,
       {"@id": "501067246e7f184553000001"},                  <5010675a6e7f18464d000001> .
       {"@id": "5010675a6e7f18464d000001"}                  wikia:event <500f28856e7f187196000001>,
    ],                                                       ...;
    "wikia:event": [                                      .
       {"@id": "500f28856e7f187196000001"},
       ...
    ]
}
More JSON-LD Features*

  • @set, @list,                                  • Embedded
        Compact IRIs,                              @context
        Unlabeled Nodes                            definitions

  • Language maps                                 • Named Graphs
  • Property generators


* http://json-ld.org/spec/latest/json-ld-syntax
History

•   2009 – Started as a way to project from the RDFa API

    •   Developers want solutions to work within HTML
        applications

    •   Desire for JSON-idiomatic way of representing RDF
        (Linked Data)

    •   Adapt existing JSON APIs to Linked Data
History

• 2011 – W3C Community Group launched
 • Broad Participation
 • Separation of Syntax from API
 • Proposed to W3C RDF 1.1 Working
   Group
History
• 2012 – RDF WG abandons other JSON
  serialization efforts (RDF/JSON)
 • JSON-LD accepted as official work item
 • Community Group drafts final report
 • RDF WG publishes JSON-LD (Syntax and
    API) as FPWD
MongoDB
• JSON-like document store
 • BSON supports extra datatypes
 • Certain key patterns are restricted
    • e.g., “.” not allowed in a key
• Query on value = pattern or value includes
  pattern
Use Case
Wikia Structured Data API
Wikia Application
• Express Wiki content as structured data
  • Wiki markup doesn’t naturally include
    semantic cues (Semantic Media Wiki
    aside).
• Add semantic markup to HTML generated
  from Wikis in RDFa
• Aggregate structured content through
  JSON-LD/MongoDB powered data service
Service Architecture
• MongoDB persistence
• JSON document representation
 • JSON-LD describedby link header
• Ruby/Sinatra web service
 • Content-negotiated access to data
    • JSON-LD, HTML, Turtle, ...
Document Model

                               {
•   Use aliases for @id and        "id": "500f1a1b6e7f1827ba000001",
                                   "type": "wikia:VideoGame",
    @type keywords                 "name": "Call of Duty: Black Ops",
                                   "publisher": [

    •   Simplifies use within          "501067246e7f184553000001",
                                      "5010675a6e7f18464d000001"
        client-side MVC            ],
                                   "wikia:event": [
        frameworks (e.g.             "500f28856e7f187196000001"
        backbone.js)               ]
                               }
Document Model

                         {
                             "id": "500f1a1b6e7f1827ba000001",
                             "type": "wikia:VideoGame",
                             "name": "Call of Duty: Black Ops",
•   Individual subject       "publisher": [
                                "501067246e7f184553000001",
    definition as Mongo          "5010675a6e7f18464d000001"
    document                 ],
                             "wikia:event": [
                                "500f28856e7f187196000001"
                             ]
                         }
Document Model

                               {
                                   "id": "500f1a1b6e7f1827ba000001",

•   Use expanded subject           "type": "wikia:VideoGame",
                                   "name": "Call of Duty: Black Ops",
    references                     "publisher": [
                                      {"id": "501067246e7f184553000001"},
                                      {"id": "5010675a6e7f18464d000001"}
    ➡This allows simple            ],
                                   "wikia:event": [
      traversal for graphify          {"id": "500f28856e7f187196000001"}
                                   ]
                               }
Document Model
                             {
                                 "id": "500f1a1b6e7f1827ba000001",

•
                                 "type": "wikia:VideoGame",
    Gather subject               "name": "Call of Duty: Black Ops",
                                 "publisher": [
    references under a              {"id": "501067246e7f184553000001"},
    hidden key                      {"id": "5010675a6e7f18464d000001"}
                                 ],
                                 "wikia:event": [
    ➡This allows easy            ],
                                    {"id": "500f28856e7f187196000001"}
      querying for objects       "_references": [
      referencing another           "501067246e7f184553000001",
                                    "5010675a6e7f18464d000001",
      object                        "500f28856e7f187196000001"
                                 ]
                             }
Document Model
                             GET http://example.com/collection/
                             500f1a1b6e7f1827ba000001

                             HTTP/1.1 200 OK
                             Content-Type: application/json;charset=utf-8
                             Link: </contexts/wikia.jsonld>; rel="describedby";
                             type="application/ld+json"

•   Return context as HTTP   {
    Link Header                  "id": "500f1a1b6e7f1827ba000001",
                                 "type": "wikia:VideoGame",
                                 "name": "Call of Duty: Black Ops",
                                 "publisher": [
                                    {"id": "501067246e7f184553000001"},
                                    {"id": "5010675a6e7f18464d000001"}
                                 ],
                                 "wikia:event": [
                                    {"id": "500f28856e7f187196000001"}
                                 ]
                             }
Restful Endpoints
                               GET http://example.com/collection/?
                               withType="schema:Corporation"
                               Accept: application/json

                               HTTP/1.1 200 OK
•   index – query collection   Content-Type: application/json;charset=utf-8
                               Link: </contexts/wikia.jsonld>; rel="describedby";
                               type="application/ld+json"
    •   by type – return       [
        objects having (or         {
        containing) a type           "id": "501067246e7f184553000001",
                                     "type": "schema:Corporation",
                                     "name": "Activision",
                                     "url": "http://callofduty.wikia.com/wiki/Activision"
                                   }, {
                                     "id": "5010675a6e7f18464d000001",
                                     "type": "schema:Corporation",
                                     "name": "Square Enix (Japan)"
                                   }
                               ]
Restful Endpoints
•
                               GET http://example.com/collection/?
    index – query collection   referencing="500f1a1b6e7f1827ba000001"
                               Accept: application/json

    •   by referencing –       HTTP/1.1 200 OK
        return objects         Content-Type: application/json;charset=utf-8
                               Link: </contexts/wikia.jsonld>; rel="describedby";
        referencing another    type="application/ld+json"
        object                 [{
                                 "id": "500f28856e7f187196000001",

    •   Build out space          "cod:game": {"id": "500f1a1b6e7f1827ba000001"},
                                 "schema:name": "Operation 40",
        around an object         "schema:startDate": "1961-04-17T00:00:00",
                                 "wikia:eventIn": [{"id": "500f1a1b6e7f1827ba000001"}],
                                 "wikia:next": {"id": "500f44556e7f18f7ef000001"},

    •   Similar to SPARQL        "wikia:objective": [
                                    {"id": "501445266e7f1847c6000001"},
        describe                    {"id": "50143e1e6e7f18256d000001"},
                                    ...
                                 ],
                               }, ...]
Restful Endpoints
                          GET http://example.com/collection/
                          500f1a1b6e7f1827ba000001
                          Accept: application/json

                          HTTP/1.1 200 OK
                          Content-Type: application/json;charset=utf-8
                          Link: </contexts/wikia.jsonld>; rel="describedby";

•
                          type="application/ld+json"
    GET – return single
                          {
    object                    "id": "500f1a1b6e7f1827ba000001",
                              "type": "wikia:VideoGame",
                              "name": "Call of Duty: Black Ops",
                              "publisher": [
                                {"id": "501067246e7f184553000001"},
                                {"id": "5010675a6e7f18464d000001"}
                              ]
                          }
Restful Endpoints
                               POST http://example.com/collection/
                               Accept: application/json
                               Content-Type: application/json

                               {

•   POST – Create new              "type": "wikia:VideoGame",
                                   "name": "Call of Duty: Black Ops"
    object                     }
                               HTTP/1.1 201 Created

    •
                               Content-Type: application/json;charset=utf-8
        Good practice to       Link: </contexts/wikia.jsonld>; rel="describedby";
                               type="application/ld+json"
        maintain dateCreated   Location: http://example.com/collection/
        and dateModified        500f1a1b6e7f1827ba000001

        equivalents            {
                                   "id": "500f1a1b6e7f1827ba000001",
                                   "type": "wikia:VideoGame",
                                   "name": "Call of Duty: Black Ops",
                                   "dateCreated": "2012-08-23T14:00:00-08:00",
                                   "dateModified": "2012-08-23T14:00:00-08:00",
                               }
Restful Endpoints
                             PUT http://example.com/collection/
                             500f1a1b6e7f1827ba000001
                             Accept: application/json
                             Content-Type: application/json

                             HTTP/1.1 200 OK
                             Content-Type: application/json;charset=utf-8
•   PUT – Update object      Link: </contexts/wikia.jsonld>; rel="describedby";
                             type="application/ld+json"


    •   Good practice to     {
                                 "id": "500f1a1b6e7f1827ba000001",
        update dateModified       "type": "wikia:VideoGame",
                                 "name": "Call of Duty: Black Ops",
        equivalent               "publisher": [
                                    {"id": "501067246e7f184553000001"},
                                    {"id": "5010675a6e7f18464d000001"}
                                 ],
                                 "dateCreated": "2012-08-23T14:00:00-08:00",
                                 "dateModified": "2012-08-23T14:15:00-08:00",
                             }
Restful Endpoints


                       DELETE http://example.com/collection/
•   DELETE – Destroy   500f1a1b6e7f1827ba000001

    object             HTTP/1.1 204 No Content
Restful Endpoints
                                GET http://example.com/collection/
                                500f1a1b6e7f1827ba000001/publisher/
                                Accept: application/json

                                HTTP/1.1 200 OK

•   path – relational query     Content-Type: application/json;charset=utf-8
                                Link: </contexts/wikia.jsonld>; rel="describedby";
                                type="application/ld+json"

    •   Return objects having   [
        a property                  {
                                    "id": "501067246e7f184553000001",
        relationship with           "type": "schema:Corporation",
        another object              "name": "Activision",
                                    "url": "http://callofduty.wikia.com/wiki/
                                Activision"
                                  }, {
                                    "id": "5010675a6e7f18464d000001",
                                    "type": "schema:Corporation",
                                    "name": "Square Enix (Japan)"
                                  }
                                ]
Restful Endpoints
                              GET http://example.com/collection/
                              500f1a1b6e7f1827ba000001
                              Accept: application/ld+json

                              HTTP/1.1 200 OK
                              Content-Type: application/ld+json;charset=utf-8


•   GET – as explicit JSON-   {
                                  "@context": "/contexts/wikia.jsonld",
    LD                            "id": "500f1a1b6e7f1827ba000001",
                                  "type": "wikia:VideoGame",
                                  "name": "Call of Duty: Black Ops",
                                  "publisher": [
                                    {"id": "501067246e7f184553000001"},
                                    {"id": "5010675a6e7f18464d000001"}
                                  ]
                              }
Working with data
•   Application Structure

    •   Ruby/Sinatra REST
        service

    •   JavaScript/Backbone.js
        client
                                 {
•   Alias JSON-LD                    "@context": {
                                       "id":     "@id",
    keywords for
                                       "type":     "@type"
    convenience
                                     }
                                 }
MVC Client
      • Natural access from client-side MVC (e.g.,
            backbone.js)

                                          Collection
// Object collection, handles objects constructed from OWL classes and properties.
// Initial fetch is only for VideoGame types, as referenced objects are
// fetched, they are added to the collection.
Wikia.ObjectCollection = Backbone.Collection.extend({
  initialize: function() { this.model = Wikia.ObjectModel; },
  url: function() { return "/api/#{@vers}/#{@name}"; },
  comparator: function(model) { return model.get('schema:name') }
  ...
}
MVC Client
       • Natural access from client-side MVC (e.g.,
             backbone.js)

                                                  Model
// OWL model class and sub-classes for dealing with owl:Class,
// owl:DatatypeProperty, owl:ObjectProperty and owl:Datatype
Wikia.ObjectModel Backbone.Model.extend({
  referencedObjects: function() { return this.resolve(_.flatten(_.toArray(this.attributes))); },
  getModel: function(key, options) { return this._resolve this.get(key)) },
  setModel: function(key, value) {...},
  _resolve: function(value) {...},
  ...
}
Summary
•   JSON-LD is a light-weight layer for representing
    linked data in JSON
•   The MongoDB document model is a natural fit for
    JSON-LD
    •   Not optimized for SPARQL; consider alternatives
•   Single Page Applications benefit from linked data
    principles
    •   RDF with OWL can be powerful when used
        appropriately in the client
Resources
•   JSON-LD Syntax
    •   http://w3.org/TR/json-ld-syntax
•   JSON-LD API
    •   http://w3.org/TR/json-ld-api
•   Git Repo
    •   https://github.com/json-ld/json-ld.org
•   Information/Playground
    •   http://json-ld.org/
•   IRC
    •   #json-ld on Freenode
More Information

   json-ld.org              JavaScript
                               Ruby
rdf-comments@w3.org             Python
                                  PHP
                                     Java
 Gregg Kellogg
 gregg@greggkellogg.net
 http://greggkellogg.net/
 @gkellogg

JSON-LD and MongoDB

  • 1.
    JSON-LD and MongoDB Powering Linked Web Apps Gregg Kellogg gregg@greggkellogg.net @gkellogg
  • 2.
    JSON-LD and Mongo •JSON-LD – graph expression in JSON • MongoDB – easily query JSON documents • Together – efficient graph query optimized for client-side processing
  • 3.
    Use Case • WebApps:Single Page Applications (SPAS) • Use JSON as native object representation • REST access to web service mirroring objects • MongoDB document store maintaining equivalent object representations • Data is linked, internally and externally (RDF)
  • 4.
    JSON-LD @graph @context @id JSON-based syntax to express linked data @language @value @list @vocab @type @set
  • 5.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], "name": "Call of Duty: Black Ops", "publisher": [ {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 6.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", Context defines terms "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], "name": "Call of Duty: Black Ops", "publisher": [ {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 7.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", Context defines terms "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", Identifier treated as IRI "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], "name": "Call of Duty: Black Ops", "publisher": [ {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 8.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", Context defines terms "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", Identifier treated as IRI "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", Type same as rdf:type "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], "name": "Call of Duty: Black Ops", "publisher": [ {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 9.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", Context defines terms "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", Identifier treated as IRI "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", Type same as rdf:type "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], Data-typed values "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], "name": "Call of Duty: Black Ops", "publisher": [ {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 10.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", Context defines terms "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", Identifier treated as IRI "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", Type same as rdf:type "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], Data-typed values "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], Simple string values "name": "Call of Duty: Black Ops", "publisher": [ {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 11.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", Context defines terms "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", Identifier treated as IRI "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", Type same as rdf:type "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], Data-typed values "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], Simple string values "name": "Call of Duty: Black Ops", "publisher": [ (unordered) arrays of values {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 12.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", Context defines terms "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", Identifier treated as IRI "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", Type same as rdf:type "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], Data-typed values "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], Simple string values "name": "Call of Duty: Black Ops", "publisher": [ (unordered) arrays of values {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], subject reference links to other resources "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 13.
    JSON, as expected { "@context": "/contexts/wikia.jsonld", Context defines terms "@id": "500f1a1b6e7f1827ba000001", "@type": "wikia:VideoGame", Identifier treated as IRI "contentRating": [ "ESRB: Mature (DS version is Teen)", "PEGI: 18+ (DS version is 16+) ", Type same as rdf:type "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], Data-typed values "datePublished": "2011-11-09", "description": "Primary game entry point", "genre": ["First-person shooter"], Simple string values "name": "Call of Duty: Black Ops", "publisher": [ (unordered) arrays of values {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ], subject reference links to other resources "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", Arrays may be ordered in @context "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 14.
    JSON-LD context { "@context": "/contexts/wikia.jsonld", { "@id": "500f1a1b6e7f1827ba000001", "@context": { "@type": "wikia:VideoGame", "wikia": "http://data.wikia.com/terms#", "contentRating": [ "xsd": "http://www.w3.org/2001/XMLSchema#", "ESRB: Mature (DS version is Teen)", "@vocab": "http://schema.org/", "PEGI: 18+ (DS version is 16+) ", "@language": "en", "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" ], "dateCreated": {"@type": "xsd:dateTime"}, "datePublished": "2011-11-09", "dateModified": {"@type": "xsd:dateTime"}, "description": "Primary game entry point", "event": {"@id": "wikia:event", "genre": ["First-person shooter"], "@type": "@id", "name": "Call of Duty: Black Ops", "@container": "@list"}, "publisher": [ "startDate": {"@type": "xsd:dateTime"}, {"@id": "501067246e7f184553000001"}, "width": {"@type": "xsd:integer"} {"@id": "5010675a6e7f18464d000001"} } ], } "event": [ "500f28856e7f187196000001", "500f44556e7f18f7ef000001", "500f449e6e7f18f94b000001", "500f44e26e7f18fa75000001" ], "wikia:platform": ["Xbox 360","PS3","PC","Wii","DS"] }
  • 15.
    Syntactic Conventions • Keysrepresent unique properties • Values may be singular or multiple • May use strings for most value representations, with typing information maintained in a context.
  • 16.
    Unique properties { Expanded Form: "http://schema.org/publisher": [ {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ] } { Compact Form: "publisher": [ "501067246e7f184553000001", "5010675a6e7f18464d000001" ] } Context: { "@context": { "@vocab": "http://schema.org/", "publisher":{"@type": "@id"}, ... } }
  • 17.
    Language tagged values { Expanded Form: "http://schema.org/name": { "@value": "Call of Duty: Black Ops", "@language": "en" } } Compact Form: { "name": "Call of Duty: Black Ops" } Context: { "@context": { "@vocab": "http://schema.org/", "@language": "en", ... } }
  • 18.
    Typed values { Expanded Form: "http://schema.org/datePublished": { "@value": "2011-11-09", "@type": "xsd:dateTime" } } Compact Form: { "datePublished": "2011-11-09" } { Context: "@context": { "@vocab": "http://schema.org/", "xsd": "http://www.w3.org/2001/XMLSchema#", "datePublished":{"@type": "xsd:dateTime"}, ... } }
  • 19.
    Subject references { Expanded Form: "http://schema.org/publisher": [ {"@id": "501067246e7f184553000001"}, {"@id": "5010675a6e7f18464d000001"} ] } { Compact Form: "publisher": [ "501067246e7f184553000001", "5010675a6e7f18464d000001" ] } Context: { "@context": { "@vocab": "http://schema.org/", "publisher":{"@type": "@id"}, ... } }
  • 20.
    Nesting Flattened Form Nested Form: { { "@context": "/contexts/wikia.jsonld", "@context": "/contexts/wikia.jsonld", "@graph": [ "@id": "500f1a1b6e7f1827ba000001", { "@type": "wikia:VideoGame", "@id": "500f1a1b6e7f1827ba000001", "name": "Call of Duty: Black Ops", "@type": "wikia:VideoGame", "publisher": [ "name": "Call of Duty: Black Ops", { "publisher": [ "@id": "501067246e7f184553000001", "501067246e7f184553000001", "name": "Activision", "5010675a6e7f18464d000001" "url": "http://callofduty.wikia.com/wiki/Activision", ] "@type": "schema:Corporation" }, { }, { "@id": "501067246e7f184553000001", "@id": "5010675a6e7f18464d000001", "name": "Activision", "@type": "schema:Corporation", "url": "http://callofduty.wikia.com/wiki/Activision", "name": "Square Enix (Japan)" "@type": "schema:Corporation" } }, { ] "@id": "5010675a6e7f18464d000001", } "@type": "schema:Corporation", "name": "Square Enix (Japan)" } ] }
  • 21.
    Nesting Flattened Form Nested Form: { { "@context": "/contexts/wikia.jsonld", "@context": "/contexts/wikia.jsonld", "@graph": [ "@id": "500f1a1b6e7f1827ba000001", { "@type": "wikia:VideoGame", "@id": "500f1a1b6e7f1827ba000001", "name": "Call of Duty: Black Ops", "@type": "wikia:VideoGame", "publisher": [ "name": "Call of Duty: Black Ops", { "publisher": [ "@id": "501067246e7f184553000001", "501067246e7f184553000001", "name": "Activision", "5010675a6e7f18464d000001" "url": "http://callofduty.wikia.com/wiki/Activision", ] "@type": "schema:Corporation" }, { }, { "@id": "501067246e7f184553000001", "@id": "5010675a6e7f18464d000001", "name": "Activision", "@type": "schema:Corporation", "url": "http://callofduty.wikia.com/wiki/Activision", "name": "Square Enix (Japan)" "@type": "schema:Corporation" } }, { ] "@id": "5010675a6e7f18464d000001", } "@type": "schema:Corporation", "name": "Square Enix (Japan)" } ] }
  • 22.
    Nesting Flattened Form Nested Form: { { "@context": "/contexts/wikia.jsonld", "@context": "/contexts/wikia.jsonld", "@graph": [ "@id": "500f1a1b6e7f1827ba000001", { "@type": "wikia:VideoGame", "@id": "500f1a1b6e7f1827ba000001", "name": "Call of Duty: Black Ops", "@type": "wikia:VideoGame", "publisher": [ "name": "Call of Duty: Black Ops", { "publisher": [ "@id": "501067246e7f184553000001", "501067246e7f184553000001", "name": "Activision", "5010675a6e7f18464d000001" "url": "http://callofduty.wikia.com/wiki/Activision", ] "@type": "schema:Corporation" }, { }, { "@id": "501067246e7f184553000001", "@id": "5010675a6e7f18464d000001", "name": "Activision", "@type": "schema:Corporation", "url": "http://callofduty.wikia.com/wiki/Activision", "name": "Square Enix (Japan)" "@type": "schema:Corporation" } }, { ] "@id": "5010675a6e7f18464d000001", } "@type": "schema:Corporation", "name": "Square Enix (Japan)" } ] }
  • 23.
    In-memory linking Flattened Form Linked Form: { "@id": "500f1a1b6e7f1827ba000001", @id 500f1a1b6e7f1827ba000001 "type": "wikia:VideoGame", "schema:name": "Call of Duty: Black Ops", type wikia:VideoGame "wikia:event": [ {"@id": "500f28856e7f187196000001"}, name "Call of Duty: Black Ops" {"@id": "500f44556e7f18f7ef000001"}, event 500f28856e7f187196000001 {"@id": "500f449e6e7f18f94b000001"}, {"@id": "500f44e26e7f18fa75000001"} ] }, { @id 500f28856e7f187196000001 "@id": "500f28856e7f187196000001", type cod:Mission "type": "cod:Mission", "schema:name": "Operation 40", name "Operation 40" "schema:startDate": "1961-04-17", startDate "1961-04-17" "wikia:eventIn": [ {"@id": "500f1a1b6e7f1827ba000001"} event 500f1a1b6e7f1827ba000001 ] }
  • 24.
    Turtle Mapping { @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . "@context": "/contexts/wikia.jsonld", @prefix schema: <http://schema.org/> . "@id": "500f1a1b6e7f1827ba000001", @prefix wikia: <http://data.wikia.com/terms#> . "@type": "wikia:VideoGame", @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . "contentRating": [ "ESRB: Mature (DS version is Teen)", <500f1a1b6e7f1827ba000001> a wikia:VideoGame; "PEGI: 18+ (DS version is 16+) ", schema:contentRating "ESRB: Mature (DS version is Teen)"@en, "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)" "PEGI: 18+ (DS version is 16+) "@en, ], "USK: 18 CERO: Z OFLC: MA15+ (DS version is M)"@en; "datePublished": "2011-11-09", schema:datePublished: "2011-11-09"^^xsd:dateTime; "name": "Call of Duty: Black Ops", schema:name "Call of Duty: Black Ops"@en; "publisher": [ schema:publisher <501067246e7f184553000001>, {"@id": "501067246e7f184553000001"}, <5010675a6e7f18464d000001> . {"@id": "5010675a6e7f18464d000001"} wikia:event <500f28856e7f187196000001>, ], ...; "wikia:event": [ . {"@id": "500f28856e7f187196000001"}, ... ] }
  • 25.
    More JSON-LD Features* • @set, @list, • Embedded Compact IRIs, @context Unlabeled Nodes definitions • Language maps • Named Graphs • Property generators * http://json-ld.org/spec/latest/json-ld-syntax
  • 26.
    History • 2009 – Started as a way to project from the RDFa API • Developers want solutions to work within HTML applications • Desire for JSON-idiomatic way of representing RDF (Linked Data) • Adapt existing JSON APIs to Linked Data
  • 27.
    History • 2011 –W3C Community Group launched • Broad Participation • Separation of Syntax from API • Proposed to W3C RDF 1.1 Working Group
  • 28.
    History • 2012 –RDF WG abandons other JSON serialization efforts (RDF/JSON) • JSON-LD accepted as official work item • Community Group drafts final report • RDF WG publishes JSON-LD (Syntax and API) as FPWD
  • 29.
    MongoDB • JSON-like documentstore • BSON supports extra datatypes • Certain key patterns are restricted • e.g., “.” not allowed in a key • Query on value = pattern or value includes pattern
  • 30.
  • 31.
    Wikia Application • ExpressWiki content as structured data • Wiki markup doesn’t naturally include semantic cues (Semantic Media Wiki aside). • Add semantic markup to HTML generated from Wikis in RDFa • Aggregate structured content through JSON-LD/MongoDB powered data service
  • 32.
    Service Architecture • MongoDBpersistence • JSON document representation • JSON-LD describedby link header • Ruby/Sinatra web service • Content-negotiated access to data • JSON-LD, HTML, Turtle, ...
  • 33.
    Document Model { • Use aliases for @id and "id": "500f1a1b6e7f1827ba000001", "type": "wikia:VideoGame", @type keywords "name": "Call of Duty: Black Ops", "publisher": [ • Simplifies use within "501067246e7f184553000001", "5010675a6e7f18464d000001" client-side MVC ], "wikia:event": [ frameworks (e.g. "500f28856e7f187196000001" backbone.js) ] }
  • 34.
    Document Model { "id": "500f1a1b6e7f1827ba000001", "type": "wikia:VideoGame", "name": "Call of Duty: Black Ops", • Individual subject "publisher": [ "501067246e7f184553000001", definition as Mongo "5010675a6e7f18464d000001" document ], "wikia:event": [ "500f28856e7f187196000001" ] }
  • 35.
    Document Model { "id": "500f1a1b6e7f1827ba000001", • Use expanded subject "type": "wikia:VideoGame", "name": "Call of Duty: Black Ops", references "publisher": [ {"id": "501067246e7f184553000001"}, {"id": "5010675a6e7f18464d000001"} ➡This allows simple ], "wikia:event": [ traversal for graphify {"id": "500f28856e7f187196000001"} ] }
  • 36.
    Document Model { "id": "500f1a1b6e7f1827ba000001", • "type": "wikia:VideoGame", Gather subject "name": "Call of Duty: Black Ops", "publisher": [ references under a {"id": "501067246e7f184553000001"}, hidden key {"id": "5010675a6e7f18464d000001"} ], "wikia:event": [ ➡This allows easy ], {"id": "500f28856e7f187196000001"} querying for objects "_references": [ referencing another "501067246e7f184553000001", "5010675a6e7f18464d000001", object "500f28856e7f187196000001" ] }
  • 37.
    Document Model GET http://example.com/collection/ 500f1a1b6e7f1827ba000001 HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8 Link: </contexts/wikia.jsonld>; rel="describedby"; type="application/ld+json" • Return context as HTTP { Link Header "id": "500f1a1b6e7f1827ba000001", "type": "wikia:VideoGame", "name": "Call of Duty: Black Ops", "publisher": [ {"id": "501067246e7f184553000001"}, {"id": "5010675a6e7f18464d000001"} ], "wikia:event": [ {"id": "500f28856e7f187196000001"} ] }
  • 38.
    Restful Endpoints GET http://example.com/collection/? withType="schema:Corporation" Accept: application/json HTTP/1.1 200 OK • index – query collection Content-Type: application/json;charset=utf-8 Link: </contexts/wikia.jsonld>; rel="describedby"; type="application/ld+json" • by type – return [ objects having (or { containing) a type "id": "501067246e7f184553000001", "type": "schema:Corporation", "name": "Activision", "url": "http://callofduty.wikia.com/wiki/Activision" }, { "id": "5010675a6e7f18464d000001", "type": "schema:Corporation", "name": "Square Enix (Japan)" } ]
  • 39.
    Restful Endpoints • GET http://example.com/collection/? index – query collection referencing="500f1a1b6e7f1827ba000001" Accept: application/json • by referencing – HTTP/1.1 200 OK return objects Content-Type: application/json;charset=utf-8 Link: </contexts/wikia.jsonld>; rel="describedby"; referencing another type="application/ld+json" object [{ "id": "500f28856e7f187196000001", • Build out space "cod:game": {"id": "500f1a1b6e7f1827ba000001"}, "schema:name": "Operation 40", around an object "schema:startDate": "1961-04-17T00:00:00", "wikia:eventIn": [{"id": "500f1a1b6e7f1827ba000001"}], "wikia:next": {"id": "500f44556e7f18f7ef000001"}, • Similar to SPARQL "wikia:objective": [ {"id": "501445266e7f1847c6000001"}, describe {"id": "50143e1e6e7f18256d000001"}, ... ], }, ...]
  • 40.
    Restful Endpoints GET http://example.com/collection/ 500f1a1b6e7f1827ba000001 Accept: application/json HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8 Link: </contexts/wikia.jsonld>; rel="describedby"; • type="application/ld+json" GET – return single { object "id": "500f1a1b6e7f1827ba000001", "type": "wikia:VideoGame", "name": "Call of Duty: Black Ops", "publisher": [ {"id": "501067246e7f184553000001"}, {"id": "5010675a6e7f18464d000001"} ] }
  • 41.
    Restful Endpoints POST http://example.com/collection/ Accept: application/json Content-Type: application/json { • POST – Create new "type": "wikia:VideoGame", "name": "Call of Duty: Black Ops" object } HTTP/1.1 201 Created • Content-Type: application/json;charset=utf-8 Good practice to Link: </contexts/wikia.jsonld>; rel="describedby"; type="application/ld+json" maintain dateCreated Location: http://example.com/collection/ and dateModified 500f1a1b6e7f1827ba000001 equivalents { "id": "500f1a1b6e7f1827ba000001", "type": "wikia:VideoGame", "name": "Call of Duty: Black Ops", "dateCreated": "2012-08-23T14:00:00-08:00", "dateModified": "2012-08-23T14:00:00-08:00", }
  • 42.
    Restful Endpoints PUT http://example.com/collection/ 500f1a1b6e7f1827ba000001 Accept: application/json Content-Type: application/json HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8 • PUT – Update object Link: </contexts/wikia.jsonld>; rel="describedby"; type="application/ld+json" • Good practice to { "id": "500f1a1b6e7f1827ba000001", update dateModified "type": "wikia:VideoGame", "name": "Call of Duty: Black Ops", equivalent "publisher": [ {"id": "501067246e7f184553000001"}, {"id": "5010675a6e7f18464d000001"} ], "dateCreated": "2012-08-23T14:00:00-08:00", "dateModified": "2012-08-23T14:15:00-08:00", }
  • 43.
    Restful Endpoints DELETE http://example.com/collection/ • DELETE – Destroy 500f1a1b6e7f1827ba000001 object HTTP/1.1 204 No Content
  • 44.
    Restful Endpoints GET http://example.com/collection/ 500f1a1b6e7f1827ba000001/publisher/ Accept: application/json HTTP/1.1 200 OK • path – relational query Content-Type: application/json;charset=utf-8 Link: </contexts/wikia.jsonld>; rel="describedby"; type="application/ld+json" • Return objects having [ a property { "id": "501067246e7f184553000001", relationship with "type": "schema:Corporation", another object "name": "Activision", "url": "http://callofduty.wikia.com/wiki/ Activision" }, { "id": "5010675a6e7f18464d000001", "type": "schema:Corporation", "name": "Square Enix (Japan)" } ]
  • 45.
    Restful Endpoints GET http://example.com/collection/ 500f1a1b6e7f1827ba000001 Accept: application/ld+json HTTP/1.1 200 OK Content-Type: application/ld+json;charset=utf-8 • GET – as explicit JSON- { "@context": "/contexts/wikia.jsonld", LD "id": "500f1a1b6e7f1827ba000001", "type": "wikia:VideoGame", "name": "Call of Duty: Black Ops", "publisher": [ {"id": "501067246e7f184553000001"}, {"id": "5010675a6e7f18464d000001"} ] }
  • 46.
    Working with data • Application Structure • Ruby/Sinatra REST service • JavaScript/Backbone.js client { • Alias JSON-LD "@context": { "id": "@id", keywords for "type": "@type" convenience } }
  • 47.
    MVC Client • Natural access from client-side MVC (e.g., backbone.js) Collection // Object collection, handles objects constructed from OWL classes and properties. // Initial fetch is only for VideoGame types, as referenced objects are // fetched, they are added to the collection. Wikia.ObjectCollection = Backbone.Collection.extend({ initialize: function() { this.model = Wikia.ObjectModel; }, url: function() { return "/api/#{@vers}/#{@name}"; }, comparator: function(model) { return model.get('schema:name') } ... }
  • 48.
    MVC Client • Natural access from client-side MVC (e.g., backbone.js) Model // OWL model class and sub-classes for dealing with owl:Class, // owl:DatatypeProperty, owl:ObjectProperty and owl:Datatype Wikia.ObjectModel Backbone.Model.extend({ referencedObjects: function() { return this.resolve(_.flatten(_.toArray(this.attributes))); }, getModel: function(key, options) { return this._resolve this.get(key)) }, setModel: function(key, value) {...}, _resolve: function(value) {...}, ... }
  • 49.
    Summary • JSON-LD is a light-weight layer for representing linked data in JSON • The MongoDB document model is a natural fit for JSON-LD • Not optimized for SPARQL; consider alternatives • Single Page Applications benefit from linked data principles • RDF with OWL can be powerful when used appropriately in the client
  • 50.
    Resources • JSON-LD Syntax • http://w3.org/TR/json-ld-syntax • JSON-LD API • http://w3.org/TR/json-ld-api • Git Repo • https://github.com/json-ld/json-ld.org • Information/Playground • http://json-ld.org/ • IRC • #json-ld on Freenode
  • 51.
    More Information json-ld.org JavaScript Ruby rdf-comments@w3.org Python PHP Java Gregg Kellogg gregg@greggkellogg.net http://greggkellogg.net/ @gkellogg

Editor's Notes

  • #2 \n
  • #3 \n
  • #4 \n
  • #5 JSON-LD brings a standard representation for expressing entity-value relationships using a few standard keywords and a consistent organizational structure for JSON Objects.\nObjects represent entities, with keys acting as properties.\n Properties always expand to full IRIs.\nArrays express a set of values associated with a property, unordered by default.\n Order expressed in @context or as an expanded value representation.\nValues are Object, string or native, with standard XSD representations for native types.\n Expanded form allows for more datatype and language variations.\n
  • #6 \n
  • #7 \n
  • #8 \n
  • #9 \n
  • #10 \n
  • #11 \n
  • #12 \n
  • #13 \n
  • #14 \n
  • #15 \n
  • #16 \n
  • #17 \n
  • #18 \n
  • #19 \n
  • #20 \n
  • #21 \n
  • #22 \n
  • #23 It&amp;#x2019;s important to note that JSON-LD is a product of the W3C RDF Working group, and is as much &amp;#x201C;RDF&amp;#x201D; as any other serialization format.\nIn this case, we show a transformation from the JSON-LD format of a resource description to Turtle, an RDF format specifically intended to be humanly readable.\n
  • #24 \n
  • #25 \n
  • #26 \n
  • #27 \n
  • #28 \n
  • #29 \n
  • #30 \n
  • #31 \n
  • #32 \n
  • #33 \n
  • #34 \n
  • #35 \n
  • #36 \n
  • #37 \n
  • #38 \n
  • #39 \n
  • #40 \n
  • #41 \n
  • #42 \n
  • #43 \n
  • #44 \n
  • #45 \n
  • #46 \n
  • #47 \n
  • #48 \n
  • #49 \n
  • #50 \n
  • #51 \n
  • #52 \n
  • #53 \n
  • #54 Subject reference identifies an object with @id in the same document, or references an external document (Linked Data).\n
  • #55 \n
  • #56 \n
  • #57 What I&apos;ve outlined is not really optimized for SPARQL. For performance, you&apos;re much better at storing triples as documents, then full-on subject definitions.\n\nThis application is more tuned for returning collections of subject definitions based on a fairly narrow query bounds (resources relevant to a particular point in game play) then general querying. In fact, I&apos;ve considered that an evolution of the application I&apos;m working on may well go to a generic SPARQL store, with good JSON-LD support, such as Stardog.\n\n
  • #58 \n
  • #59 \n