JSON-LD Framing allows developers to query by example and
force a specific tree layout to a JSON-LD document.
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.
How to Read this Document
This document is a detailed specification for a serialization of Linked
Data in JSON. The document is primarily intended for the following audiences:
- Authors who want to query JSON-LD documents to create representations
more appropriate for a given use case.
- Software developers that want to implement processors and APIs for
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
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:
- JSON object
- An object structure is represented as a pair of curly brackets surrounding zero or
more name-value pairs. A name is a string. A single colon comes after
each name, separating the name from the value. A single comma separates a value
from a following name. The names within an object SHOULD be unique.
- An array is represented as square brackets surrounding zero or more
values that are separated by commas.
- A string is a sequence of zero or more Unicode (UTF-8) characters,
wrapped in double quotes, using backslash escapes (if necessary). A
character is represented as a single character string.
- A number is similar to that used in most programming languages, except
that the octal and hexadecimal formats are not used and that leading
zeros are not allowed.
- true and false
- Values that are used to express one of two possible boolean states.
- The use of the null value within JSON-LD is used to ignore or reset values.
- A JSON key that is specific to JSON-LD, specified in the JSON-LD Syntax specification [[!JSON-LD]]
in the section titled Syntax Tokens and Keywords.
- A a set of rules for interpreting a JSON-LD document as specified in
The Context of the [[JSON-LD]] specification.
- An Internationalized Resource Identifier as described in [[!RFC3987]].
- Linked Data
- A set of documents, each containing a representation of a linked data graph.
- linked data graph or dataset
- An unordered labeled directed graph, where nodes are
IRIs or Blank Nodes, or other values.
A linked data graph is a generalized representation of a
as defined in [[!RDF-CONCEPTS]].
- named graph
- A linked data graph that is identified by an IRI.
- graph name
- The IRI identifying a named graph.
- default graph
- When executing an algorithm, the graph where data should be placed
if a named graph is not specified.
- A piece of information that is represented in a linked data graph.
- node definition
- A JSON object used to represent a node and
one or more properties of that node. A JSON object is a
node definition if it does not contain the keys
@set and it has one or more keys
- node reference
- A JSON object used to reference a node having only the
- blank node
- A node in the linked data graph that does not contain a de-referenceable
identifier because it is either ephemeral in nature or does not contain information that needs to be
linked to from outside of the linked data graph. A blank node is assigned an identifier starting with
- The IRI label of an edge in a linked data graph.
- A node in a linked data graph with at least one outgoing edge, related to an object node through a property.
- A node in a linked data graph with at least one incoming edge.
- A piece of information that contains four items; a subject, a property,
an object, and a graph name.
- An object expressed as a value such as a string, number or in expanded form.
There are a number of ways that one may participate in the development of
- Technical discussion typically occurs on the public mailing list:
- Public teleconferences are held
on Tuesdays at 1500UTC on the second and fourth week of each month.
- Specification bugs and issues should be reported in the
- Source code for the
specification can be found on Github.
- The #json-ld
IRC channel is available for real-time discussion on irc.freenode.net.
The Application Programming Interface
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]].
- void frame()
Frames the given
input using the
frame according to the steps in the
Framing Algorithm. The
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.
- object or object or IRI input
- 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.
- object or IRI frame
- The frame to use when re-arranging the data of
in the form of an JSON object or as IRI.
- JsonLdCallback callback
- A callback that is called when processing is complete on
- optional JsonLdOptions? options
- A set of options that MAY affect the framing algorithm such as, e.g., the
input document's base IRI.
The 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.
Syntax Tokens and Keywords
This specification adds a number of keywords to
the ones defined in the [[!JSON-LD]] specification:
- Used in Framing to set the default value for
an output property when the framed node definition does not include such a property.
- Used in Framing to override the
value of explicit inclusion flag within a specific frame.
- Used in Framing to override the
value of omit default flag within a specific frame.
- Used in Framing to override the
value of object embed flag within a specific frame.
- Used in Framing when a value of null
should be returned, which would otherwise be removed when
All JSON-LD tokens and keywords are case-sensitive.
- active subject
the currently active subject that the processor should use when
- active property
the currently active property that the processor should use when
processing. The active property is represented in the original lexical form, which
is used for finding coercion mappings in the active context.
- active object
the currently active object that the processor should use when
- active context
a context that is used to resolve terms while the processing
algorithm is running. The active context is the context
contained within the processor state.
- compact IRI
a compact IRI is has the form of prefix and suffix and is used as a way
of expressing an IRI without needing to define separate term definitions for
each IRI contained within a common vocabulary identified by prefix.
- local context
a context that is specified within a JSON object,
specified via the
- processor state
the processor state, which includes the active
context, active subject, and
active property. The processor state is managed
as a stack with elements from the previous processor state
copied into a new processor state when entering a new
- JSON-LD input
The JSON-LD data structure that is provided as input to the algorithm.
- JSON-LD output
The JSON-LD data structure that is produced as output by the algorithm.
A term is a short word defined in a context that MAY be expanded to an IRI
A prefix is a term that expands to a vocabulary base IRI. It
is typically used along with a suffix to form a compact IRI to create an IRI
within a vocabulary.
- language-tagged string
A language-tagged string is a literal without a datatype, including
a language. See languaged-tagged string
- typed literal
A typed literal is a literal with an associated IRI
which indicates the literal's datatype.
See languaged-tagged literal in [[!RDF-CONCEPTS]].
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.
Framing Algorithm Terms
- input frame
- the initial frame provided to the framing algorithm.
- framing context
- a context containing a map of embeds, the
object embed flag, the
explicit inclusion flag and the
omit default flag.
- map of embeds
- a map that tracks if a subject is to be embedded in the output of the
Framing Algorithm; it maps a subject
@id to a parent JSON object and property
or parent array.
- object embed flag
- a flag specifying that objects should be directly embedded in the output,
instead of being referred to by their IRI.
- explicit inclusion flag
- a flag specifying that for properties to be included in the output, they
must be explicitly declared in the framing context.
- omit default flag
- a flag specifying that properties that are missing from the
JSON-LD input, but present in the input frame
should be omitted from the output.
- map of flattened subjects
- a map of subjects that is the result of the
Node Map Generation algorithm.
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
@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
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:
- Validate frame.
- Create a set of matched subjects by filtering subjects checking
the map of flattened subjects against frame:
- If frame has a
@type property containing
one or more IRIs match any node definition
@type property including any of those IRIs.
- Otherwise, if frame has a
@type property only
a empty JSON object, matches any node definition
@type property, regardless of the actual values.
- Otherwise, match if the node definition contains all of the
non-keyword properties in frame.
- Get values for embedOn and explicitOn by looking in frame
for the keys
@explicit using the current values
for object embed flag and explicit inclusion flag from state if not found.
- For each id and subject from the set of matched subjects, ordered by id:
- If the active property is null, set the map of embeds in
state to an empty map.
- Initialize output with
@id and id.
- Initialize embed with parent and active property to
- If embedOn is true, and id is in map of embeds
- Set existing to the value of id in map of embeds
and set embedOn to false.
- If existing has a parent which is an array containing a
JSON object with
@id equal to id, element has
already been embedded and can be overwritten, so set embedOn to true.
- Otherwise, existing has a parent which is a node definition.
Set embedOn to true if any of the items in parent property
is a node definition
or node reference for id because the embed can be overwritten.
- If embedOn is true, existing is already embedded but
can be overwritten, so Remove Embedded Definition for id.
- If embedOn is false, add output to parent
by either appending to parent if it is an array, or appending
to active property in parent otherwise.
- Add embed to map of embeds for id.
- Process each property and value in the matched subject, ordered
- If property is a keyword, add property and a copy of value
to output and continue with the next property from subject.
- If property is not in frame:
- If explicitOn is false, Embed values
from subject in output using subject as element and
property as active property.
- Continue to next property.
- Process each item from value as follows:
- If item is a JSON object with the key
create a JSON object named list with the key
the value of an empty array. Append list to property in
output. Process each listitem in the
@list array as follows:
- If listitem is a node reference
process listitem recursively using this algorithm passing a new map of
subjects that contains the
@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.
- Otherwise, append a copy of listitem to
@list in list.
- If item is a node reference
process item recursively using this algorithm passing a new map as
subjects that contains the
@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.
Passing a node reference doesn't work if this map
is used recursively. Presently pass node definition from original
map of flattened subjects.
- Otherwise, append a copy of item to active property in
- Process each property and value in frame,
where property is not a keyword, ordered by property:
- Set property frame to the first item in value or a newly created
JSON object if value is empty.
- Skip to the next property in frame if property is in output
or if property frame contains
@omitDefault which is true or if it does not contain
@omitDefault but the value of omit default flag
- Set the value of property in output to a new JSON object
with a property
@preserve and a value that is a copy of the value
@default in frame if it exists, or the string
- Add output to parent.
If parent is an array, append output, otherwise
append output to active property in parent.
At the completion of the recursive algorithm, results will contain the top-level
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
@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.
Remove Embedded Definition
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.
- Find embed from map of embeds for id.
- Let parent and property be from embed.
- If parent is an array, replace the node definition that matches
id with a node reference. If parent is a JSON object,
replace the node definition for property that matches id
with a node reference.
- Remove dependents for id in map of embeds
by scanning the map for entries with parent that have an
@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
This algorithm recursively embeds property values in node definition output, given a
framing context, input node definition element, active property,
- For each item in active property of element:
- If item is a JSON object with the key
then create a new JSON object with a key
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.
- If item is a node reference:
- If map of embeds does not contain an entry for the
@id of item:
- Initialize embed with output as parent and
active property as property
and add to map of embeds.
- Initialize a new node definition o to act as the
embedded node definition.
- For each property and value in the expanded definition for
item in subjects:
- Add property and a copy of value to o if property
is a keyword.
- Otherwise, recursively call this algorithm passing value as element,
property as active property and o as output.
- Set item to o.
- If output is an array, append a copy of item, otherwise
append a copy of item to active property in output.
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.
- Type name:
- Subtype name:
- Required parameters:
- Optional parameters:
- Encoding considerations:
- The same as the
application/json MIME media type.
- Security considerations:
- Since a JSON-LD frame is intended to specify a deterministic layout
for a JSON-LD graph, the serialization SHOULD NOT be passed through a
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.
- Interoperability considerations:
- Not Applicable
- Published specification:
- The JSON-LD specification.
- Applications that use this media type:
- Any programming environment that requires the exchange of
directed graphs. Implementations of JSON-LD have been created for
- Additional information:
- Magic number(s):
- Not Applicable
- File extension(s):
- Macintosh file type code(s):
- Person & email address to contact for further information:
- Manu Sporny <firstname.lastname@example.org>
- Intended usage:
- Restrictions on usage:
- Manu Sporny, Gregg Kellogg, Markus Lanthaler, Dave Longley
- Change controller:
Fragment identifiers have no meaning with
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.