This document is licensed under a Creative Commons Attribution 3.0 License.
JSON-LD Framing allows developers to query by example and force a specific tree layout to a JSON-LD document.
This document is merely a public working draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organisation.
This document is an experimental work in progress.
A JSON-LD document is a representation of a directed graph. A single directed graph can have many different serializations, each expressing exactly the same information. Developers typically work with trees, represented as JSON objects. While mapping a graph to a tree can be done, the layout of the end result must be specified in advance. A Frame can be used by a developer on a JSON-LD document to specify a deterministic layout for a graph.
This document is a detailed specification for a serialization of Linked Data in JSON. The document is primarily intended for the following audiences:
To understand the basics in this specification you must first be familiar with JSON, which is detailed in [RFC4627]. You must also understand the JSON-LD Syntax [JSON-LD], which is the base syntax used by all of the algorithms in this document, and the JSON-LD API [JSON-LD-API]. To understand the API and how it is intended to operate in a programming environment, it is useful to have working knowledge of the JavaScript programming language [ECMA-262] and WebIDL [WEBIDL]. To understand how JSON-LD maps to RDF, it is helpful to be familiar with the basic RDF concepts [RDF-CONCEPTS].
The intent of the Working Group and the Editors of this specification is to eventually align terminology used in this document with the terminology used in the RDF Concepts document to the extent to which it makes sense to do so. In general, if there is an analogue to terminology used in this document in the RDF Concepts document, the preference is to use the terminology in the RDF Concepts document.
The following is an explanation of the general terminology used in this document:
@value,
      @list or @set and it has one or more keys
      other than @id.@id key._:.There are a number of ways that one may participate in the development of this specification:
This API provides a clean mechanism that enables developers to convert JSON-LD data into a a variety of output formats that are easier to work with in various programming languages. If a JSON-LD API is provided in a programming environment, the entirety of the following API must be implemented.
The JSON-LD processor interface is the high-level programming structure that developers use to access the JSON-LD transformation methods. The definition below is an experimental extension of the interface defined in the [JSON-LD-API].
The JSON-LD API signatures are the same across all programming languages. Due
      to the fact that asynchronous programming is uncommon in certain languages, developers may
      implement processor with a synchronous interface instead. In that case, the callback
      parameter must not be included and the result must be returned as return value instead.
[NoInterfaceObject]
interface JsonLdProcessor {
    void frame (object or object[] or IRI input, object or IRI frame, object or IRI? context, JsonLdCallback callback, optional JsonLdOptions? options);
};frameinput using the
        frame according to the steps in the
        Framing Algorithm. The input
        is used to build the framed output and is returned if there are no errors.
        If there are no matches for the frame, null must be
        returned. Exceptions must be thrown if there are errors.
      | Parameter | Type | Nullable | Optional | Description | 
|---|---|---|---|---|
| input | object or object[] or IRI | ✘ | ✘ | The JSON-LD object or array of JSON-LD objects to perform the framing upon or an IRI referencing the JSON-LD document to frame. | 
| frame | object or IRI | ✘ | ✘ | The frame to use when re-arranging the data of input; either
            in the form of an JSON object or as IRI. | 
| context | object or IRI | ✔ | ✘ | An optional external context to use additionally to the context embedded in inputwhen expanding theinput. | 
| callback | JsonLdCallback | ✘ | ✘ | A callback that is called when processing is complete on
            the given input. | 
| options | JsonLdOptions | ✔ | ✔ | A set of options that may affect the framing algorithm such as, e.g., the input document's base IRI. | 
voidThe JsonLdCallback is used to return a processed JSON-LD representation as the result of processing an API method.
See JsonLdCallback definition in [JSON-LD-API].
This section describes datatype definitions used within the JSON-LD API.
The JsonLdOptions type is used to convert a set of options to an interface method.
See JsonLdOptions definition in [JSON-LD-API].
All algorithms described in this section are intended to operate on language-native data structures. That is, the serialization to a text-based JSON document isn't required as input or output to any of these algorithms and language-native data structures must be used where applicable.
This specification adds a number of keywords to the ones defined in the [JSON-LD] specification:
@default@explicit@omitDefault@embed@nullAll JSON-LD tokens and keywords are case-sensitive.
@context keyword.
    Framing is the process of taking a JSON-LD document, which expresses a graph of information, and applying a specific graph layout (called a Frame).
Framing makes use of the Node Map Generation algorithm to place each object defined in the JSON-LD document into a flat list of objects, allowing them to be operated upon by the framing algorithm.
@id to a parent JSON object and property
    or parent array.This algorithm is a work in progress. Presently, it only works for documents without named graphs.
Currently, framing allows just to select node definitions based
  on @type matching or duck typing for included properties. It allows value properties to
  be explicitly matched based on defining the property and excluding things that are undefined, but it
  does not allow to be more specific about the types of values selected. Allowing this is currently
  being discussed.
The framing algorithm takes an JSON-LD input (expanded input) and an input frame (expanded frame) that have been expanded according to the Expansion Algorithm, and a number of options and produces JSON-LD output.
Create framing context using null for the map of embeds,
    the object embed flag set to true, the
    explicit inclusion flag set to false, and the
    omit default flag set to false along with map of flattened subjects
    set to the @merged property of the result of performing the
    Node Map Generation algorithm on
    expanded input. Also create results as an empty array.
Invoke the recursive algorithm using framing context (state), the map of flattened subjects (subjects), expanded frame (frame), result as parent, and null as active property.
The following series of steps is the recursive portion of the framing algorithm:
@type property containing
        one or more IRIs match any node definition
        with a @type property including any of those IRIs.@type property only
        a empty JSON object, matches any node definition
        with a @type property, regardless of the actual values.@embed and @explicit using the current values
    for object embed flag and explicit inclusion flag from state if not found.@id and id.@id equal to id, element has
            already been embedded and can be overwritten, so set embedOn to true.@list, then
                    create a JSON object named list with the key @list and
                    the value of an empty array. Append list to property in
                    output. Process each listitem in the @list array as follows:
                    @id of listitem as the key
                        and the node definition from the original map of flattened subjects
                        as the value. Pass the first value from
                        frame for property as frame, list
                        as parent, and @list as active property.@list in list.@id of item as the key and
                    the node definition from the original map of flattened subjects
                    as the value. Pass the first value from
                    frame for property as frame, output
                    as parent, and property as active property.
                  @omitDefault which is true or if it does not contain
                @omitDefault but the value of omit default flag
                true.@preserve and a value that is a copy of the value
                of @default in frame if it exists, or the string
                @null otherwise.At the completion of the recursive algorithm, results will contain the top-level node definitions.
The final two steps of the framing algorithm require
  results to be compacted according to the
  Compaction Algorithm by using the
  context provided in the input frame. If the frame has no context, compaction
  is performed with an empty context (not a null context). The compaction result must use
  the @graph keyword at the top-level, even if the context is empty or if there
  is only one element to put in the @graph array. Subsequently, replace all key-value
  pairs where the key is @preserve with the value from the key-pair. If the value
  from the key-pair is @null, replace the value with null. If,
  after replacement, an array contains only the value null remove the value, leaving
  an empty array. The resulting value is the final JSON-LD output.
This algorithm replaces an already embedded node definition with a node reference. It then recursively removes any entries in the map of embeds that had the removed node definition in their parent chain.
About as clear as mud
The current behaviour avoids embedding the same data multiple times in the result makes it difficult to work with the output. A proposal to change this to "agressive re-embedding" is currently being discussed.
The algorithm is invoked with a framing context and subject id id.
@id of id,
    removing that definition from the map, and then removing the dependents for the parent id
    recursively by repeating this step. This step will terminate when there are no more embed
    entries containing the removed node definition's @id in their
    parent chain.This algorithm recursively embeds property values in node definition output, given a framing context, input node definition element, active property, and output.
@list,
        then create a new JSON object with a key @list and
        a value of an empty array and add it to output, appending if output
        is an array, and appending to active property otherwise. Recursively call this
        algorithm passing item as element, @list as active property,
        and the new array as output. Continue to the next item.@id of item:
            This section is non-normative.
This section is included merely for standards community review and will be submitted to the Internet Engineering Steering Group if this specification becomes a W3C Recommendation.
application/json MIME media type.eval()
    function. It is recommended that a conforming parser does not attempt to
    directly evaluate the JSON-LD frame and instead purely parse the
    input into a language-native data structure.Fragment identifiers have no meaning with application/frame-ld+json resources.
A large amount of thanks goes out to the JSON-LD Community Group participants who worked through many of the technical issues on the mailing list and the weekly telecons - of special mention are Niklas Lindström, François Daoust, and Zdenko 'Denny' Vrandečić. The editors would like to thank Mark Birbeck, who provided a great deal of the initial push behind the JSON-LD work via his work on RDFj. The work of Dave Lehn and Mike Johnson are appreciated for reviewing, and performing several implementations of the specification. Ian Davis is thanked for this work on RDF/JSON. Thanks also to Nathan Rixham, Bradley P. Allen, Kingsley Idehen, Glenn McDonald, Alexandre Passant, Danny Ayers, Ted Thibodeau Jr., Olivier Grisel, Josh Mandel, Eric Prud'hommeaux, David Wood, Guus Schreiber, Pat Hayes, Sandro Hawke, and Richard Cyganiak for their input on the specification.