Vous êtes sur la page 1sur 23

JSON Light At A Glance

March 31, 2012

JSON Light at a Glance


Contents
Motivation ..................................................................................................................................................... 2 JSON Light Design .......................................................................................................................................... 2 Response payload samples ........................................................................................................................... 3 Entry .......................................................................................................................................................... 3 Feed ........................................................................................................................................................... 4 Property ..................................................................................................................................................... 4 Entry with expanded navigation links ....................................................................................................... 5 Service document ...................................................................................................................................... 5 Entity reference links ................................................................................................................................. 6 Top-level (streaming) collections .............................................................................................................. 6 Error ........................................................................................................................................................... 7 Request payload samples .............................................................................................................................. 7 Entry .......................................................................................................................................................... 7 Entry with deep inserts.............................................................................................................................. 8 Entry with binding operations (insert or update)...................................................................................... 8 Property ..................................................................................................................................................... 9 Entity reference links ................................................................................................................................. 9 Parameters ................................................................................................................................................ 9 The metadata URL ....................................................................................................................................... 10 Annotations ................................................................................................................................................. 12 What annotations are used for ............................................................................................................... 12 Annotation Groups .................................................................................................................................. 13 Controlling the amount of control information in the payload .................................................................. 15 $metadata=default .................................................................................................................................. 15 $metadata=none ..................................................................................................................................... 15 $metadata=all.......................................................................................................................................... 15 Content Type and Payload Ordering Constraints ........................................................................................ 17 Metadata Expressions ................................................................................................................................. 18 CSDL Annotations .................................................................................................................................... 18 OData Metadata Expressions .................................................................................................................. 18 Metadata Expression Composition Rules ................................................................................................ 20 Combinator Functions ............................................................................................................................. 21 Functions in Metadata Expressions ......................................................................................................... 22 Conclusion ................................................................................................................................................... 23

1|Page

JSON Light At A Glance

March 31, 2012

Motivation
OData/WCF Data Services currently supports a JSON format that has a couple of problems. The two that inspired the design of JSON Light are: Payload size: the current JSON format is too verbose on the wire thus unnecessarily increasing the payload size of a response. As a result we now refer to the existing JSON format also as JSON verbose. Ease-of-use for JScript/jQuery processors: JSON verbose has a set of wrapper objects (especially around collections) that make the format hard to use in JScript/jQuery since these wrappers were sprinkled in between the actual data. As a result extracting the actual data (without any control information) as JSON involved stripping out all such wrappers and, for a set of clients, made it harder to access the data than it should be.

Disclaimer: this document represents preliminary thinking about a light-weight JSON format for OData. Not all aspects of this new format have been locked down yet and in particular the names and constants are likely to change.

JSON Light Design


A few requirements guided the development of the JSON Light format; the most important ones are listed below as a frame of reference but are not discussed in detail. The payload size should be minimized while preserving all the information present in the current ATOM and JSON verbose formats. The response payloads should be easy to consume in pure JScript or jQuery processors. The format should intrinsically support extensibility for future versions of OData. The format should support streaming (e.g., for endless feeds) with the assumption that only a single entry ever fits into memory. Clients should be able to control the trade-off between payload size on the wire and computational requirements on the client. The system should be fully functional with no out-of-band information in clients. Feedback from the OData/REST community should continuously influence the format to get the broadest possible support for JSON Light.

The approach we took to accomplish the above is as follows: in order to make the new format easy to process by JScript/jQuery clients, we have to continue to use a JSON representation on the wire (as opposed to a binary representation for example). Looking at the current JSON (verbose) payloads, large parts of the payload are highly stylized (for example, the edit links for all the entries in a feed might only differ in the value of the key property of the entry but otherwise be identical). To minimize the payload size, all the stylized pieces in the payload were removed from the actual wire format. Instead, expressions to compute the stylized payload parts were added in annotations to the metadata

2|Page

JSON Light At A Glance

March 31, 2012

document. These metadata expressions (together with the data on the wire) can be used by the client to re-compute all the stylized payload pieces as if they would have been on the wire directly. The extensibility story of the new JSON Light format revolves around so-called annotations in the payload. Annotations are used to non-intrusively add control information to a JSON Light payload. Such annotations can refer to a JSON object or a JSON property and provide additional information about the instance (or property). OData defines a set of annotations and custom annotations can be adding domain-specific control information to the payload. In JSON Light, annotations are used to capture control information that cannot be expressed via metadata expressions (e.g., the next link of a feed) as well as to provide a mechanism to override the values that would otherwise be computed from the expressions (e.g., if the stream read link of one particular entry points to a different server than the metadata expression for all the other entries specifies). Computing values from metadata expressions is compute intensive and some clients might choose a larger payload size over the necessity to compute expressions; as a result the new $metadata query option allows the client to control whether or not control information should be embedded into the payload or will be computed from expressions. To make JSON Light payloads support streaming scenarios, we put in place a few restrictions with respect to order in which data must appear on the wire. More details are discussed in CONTENT TYPE AND Payload Ordering Constraints. The community is engaged via a shared repository for the JSON Light spec on GitHub and via various OData distribution and mailing lists.

Response payload samples


This section provides JSON Light samples of response payloads for all the payload kinds supported in OData based on sample data from the Northwind database.

Entry
{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.NorthwindEntities/Customers/@Element" "CustomerID": "ALFKI", "CompanyName": "Alfreds Futterkiste", "ContactName": "Maria Anders", "ContactTitle": "Sales Representative", "Address": "Obere Str. 57", "City": "Berlin" }

Comments:

3|Page

JSON Light At A Glance

March 31, 2012

The odata.metadata property is an instance annotation that describes the kind and type of the payload. More details on the odata.metadata property can be found in THE METADATA URL. All other properties are regular data as you would expect in a JSON representation of a customer. Note in particular that no navigation properties are present in the payload since they are control information (e.g., the navigation link) that can be computed from metadata expressions.

Feed
{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.NorthwindEntities/Customers" "odata.count": 42, "value": [ { "CustomerID": "ALFKI", "CompanyName": "Alfreds Futterkiste", ... }, ... ], "odata.nextLink": "..." }

Comments: For non-object payloads we need a wrapper object at the top-level to store the odata.metadata property as well as other control information (e.g. the next link or count in the case of a feed, or the type name of an open primitive property). o Note that when a wrapper object is used, the actual data property is always the value of the value property. o For payloads that are represented as top-level object (e.g., entities), no wrapper is needed.

Property
{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.Customer/ContactName", "value": "Maria Anders" }

Comments: The sample above shows a primitive property payload. The same structure of top-level property payload holds for complex properties (where the value of the value property would be a JSON object) and collection properties (where the value of the value property would be a JSON array).

4|Page

JSON Light At A Glance

March 31, 2012

Entry with expanded navigation links


{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.NorthwindEntities/Orders/@Element" "OrderID": 10248, "ShipName": "Vins et alcools Chevalier", "Customer": { "CustomerID": "VINET", "ContactName": "Paul Henriot", ... }, "Order_Details@odata.count": 42, "Order_Details": [ { "OrderID": 10248, "Quantity": 12, ... }, ... ], "Order_Details@odata.nextLink": "http://northwind.odata.org/next(234234)" }

Comments: The above sample shows an order entry with expanded Customer and Order_Details navigation properties. Note that the values of the Customer and Order_Details navigation properties are a plain JSON object and a plain JSON array as they would naturally be modeled in JSON.

Service document
{ odata.metadata: " http://northwind.odata.org/$metadata" value: [ { name: "Categories" url: "http://northwind.odata.org/Categories" }, ... ] }

Comments: The service document contains an array of collections each of which consists of the name of the entity set and the URL to reach the data in the collection. Note that the URL can be a relative URL (and is made absolute in the sample only for demonstration purposes).

5|Page

JSON Light At A Glance

March 31, 2012

Entity reference links


{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.Order/Customer", "url": "http://northwind.odata.org/Customers('VINET')" } { "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.Customer/Orders", "odata.count": 42, "odata.nextLink": "http://northwind.odata.org/next(29433234)" "value": [ { "url": "http:// northwind.odata.org/Orders(10643)" }, { "url": "http:// northwind.odata.org/Orders(10692)" }, ... ], } { "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.Customer/Orders/@Element", "url": "http:// northwind.odata.org/Orders(10643)" }

Comments: The first sample shows the entity reference link for the singleton navigation property Customer on type Order. The second sample shows the entity reference links for the collection navigation property Orders on type Customer (including the next link and count of the link collection). The third sample is similar to the first one in that it has a single entity reference link; but this time the sample is a singleton entity reference link selected from the set of entity reference links for the Orders navigation property on type Customer. Note how the @Element item selector in the metadata URI indicates that the payload is a single item from a collection; more on the metadata URI and its structure can be found in THE METADATA URL.

Top-level (streaming) collections


{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.NorthwindEntities/TopTenOrderAmounts", "value": [ 33000, 27300, 25344, 21231 ] }

Comments: 6|Page

JSON Light At A Glance

March 31, 2012

A top-level (streaming) collection is a streaming collection of primitive or complex values produced by an operation (service operation, function or action). Note that the only difference between a top-level collection property and a top-level streaming collection is that the metadata URI for a (collection) property points to a property while it points to a function import in the streaming collection case.

Error
{ "odata.error": { "code": "error-code", "message": { "lang": "en-US", "value": "Error in query syntax." } } }

Comments: Note that error payloads do not have a metadata URI. Also note that top-level error payloads and in-stream errors share the same format on the wire.

Request payload samples


In OData, request payloads can be entries, entity reference links, properties and parameters. Request payloads do not have metadata URIs (the assumption is that the server processing a request has all the required information already via the request URI sent to it). Other than the missing metadata URI, request payloads are very similar in some cases identical to response payloads. The details for each request payload are described below.

Entry
{ "CustomerID": "ALFKI", "CompanyName": "Alfreds Futterkiste", "ContactName": "Maria Anders", "ContactTitle": "Sales Representative", "Address": "Obere Str. 57", "City": "Berlin" }

Comments: A typical entry can be (modified and) round-tripped to the server directly.

7|Page

JSON Light At A Glance

March 31, 2012

The odata.metadata annotation can but does not have to be removed; the server will ignore it if it is present.

Entry with deep inserts


{ "OrderID": 99999, "ShipName": "Milka Chocolate", "Customer": { "CustomerID": "NEW", "ContactName": "John Doe", ... }, "Order_Details": [ { "OrderID": 9999, "Quantity": 10, ... }, ... ] }

Comments: The above payload can be used when inserting a new order and at the same time inserting a customer and order details. The format for this payload kind (again modulo the odata.metadata annotation) is the same as for the response payload.

Entry with binding operations (insert or update)


{ "OrderID": 10248, "ShipName": "Vins et alcools Chevalier", "Customer@odata.bind": "http://northwind.odata.org/Customers(4)", "Order_Details@odata.bind": [ "http://northwind.odata.org/Order_Details(42)", "http://northwind.odata.org/Order_Details(43)", ... ], "Order_Details": [ { "OrderID": 9999, "Quantity": 10, ... }, ... ] }

8|Page

JSON Light At A Glance Comments:

March 31, 2012

When inserting or updating an entry (an order in this sample), relationships of navigation properties can be changed via bind operations. A bind operation is encoded as a property annotation on the property it belongs to and has a single value (for singleton navigation properties) or an array of values (for collection navigation properties). Note that the above payload shows that for insert scenarios, collection navigation property bind operations and deep insert operations can be combined. In this case, the bind operations have to appear before the deep insert operations in the payload. In update scenarios, only bind operations but not deep inserts are allowed.

Property
{ "value": Maria Anders }

Comments: Property payloads in requests do not differ from property payloads in responses (modulo the odata.metadata annotation).

Entity reference links


{ "url": "http://northwind.odata.org/Customers('VINET')" }

Comments: As with property payloads, entity reference link payloads do not differ from the response format (modulo the odata.metadata annotation).

Parameters
{ "param1": 42, "param2": { "Street": "One Microsoft Way", "Zip": 98052 }, "param3": [ 1, 42, 99 ] }

Comments: Parameter payloads are only supported in requests. 9|Page

JSON Light At A Glance

March 31, 2012

The values of a parameter record follow the same format rules as values for primitive, complex and collection properties.

The metadata URL


The metadata URL, i.e., the value of the odata.metadata annotation, contains all the information needed to parse a JSON Light response without additional out-of-band knowledge. It captures the URL to the actual metadata document of the service, the response kind and the type information of the data in the response. Here are the construction rules for the metadata URLs for each of the supported payload kinds:

Feed
{metadata-uri}#{schema}.{entity-container}/{entity-set} http://northwind.odata.org/$metadata#NorthwindModel.NorthwindEntities/Customers

If all entries in a feed are known to not only come from the specified set but all be of a more derived type than the base type of the set a type cast segment is added to the metadata URI
{metadata-uri}#{schema}.{entity-container}/{entity-set}/{schema}.{type-name} http://northwind.odata.org/$metadata# NorthwindModel.NorthwindEntities/Customers/NorthwindModel.DerivedCustomerType

TODO: metadata URLs for entries and feeds also allow the optional specification of the $select projection (to guide processors what metadata expressions to expand). We have not settled on naming, scope and syntax. Add this information here once we do.

Entry
{metadata-uri}#{schema}.{entity-container}/{entity-set}/@Element http://northwind.odata.org/$metadata# NorthwindModel.NorthwindEntities/Customers/@Element

If the entry is known to be of a more derived type than the base type of the set a type cast segment is added to the metadata URI
{metadata-uri}#{schema}.{entity-container}/{entity-set}/{schema.}{type-name}/@Element http://northwind.odata.org/$metadata# NorthwindModel.NorthwindEntities/Customers/NorthwindModel.DerivedCustomer/@Element

Property
10 | P a g e

JSON Light At A Glance

March 31, 2012

A property payload can be produced either by a query for the value of a property or by calling an operation (service operation, function, action).
{metadata-uri}#{schema}.{type-name}/{property-name} http://northwind.odata.org/$metadata# NorthwindModel.NorthwindEntities/Customers(ALFKI)/ContactName {metadata-uri}#{schema}.{entity-container}/{function-import-name} http://northwind.odata.org/$metadata# NorthwindModel.NorthwindEntities/TopTenOrderAmounts

Service Document
The metadata URI in a service document is the URI of the metadata document itself
{metadata-uri} http://northwind.odata.org/$metadata

Top-level collection
Such streamable collections of primitive and complex types are only produced by operations (service operations, functions, actions)
{metadata-uri}#{schema}.{entity-container}/{function-import-name} http://northwind.odata.org/$metadata# NorthwindModel.NorthwindEntities/TopTenOrderAmounts

Entity reference links


The metadata URI for an entity reference link payload is the navigation property the entity reference link(s) refer to. When selecting a single entity reference link from a collection of links, the @Element item selector is appended to the metadata URI.
{metadata-uri}#{schema}.{type-name}/{singleton-nav-prop} http://northwind.odata.org/$metadata#NorthwindModel.Order/Customer {metadata-uri}#{schema}.{type-name}/{collection-nav-prop} http://northwind.odata.org/$metadata#NorthwindModel.Customer/Orders {metadata-uri}#{schema}.{type-name}/{collection-nav-prop}/@Element http://northwind.odata.org/$metadata#NorthwindModel.Customer/Orders/@Element

Error
No metadata URI exists for a top-level error payload 11 | P a g e

JSON Light At A Glance

March 31, 2012

Parameters
No metadata URI exists for parameter payloads because they can only appear in requests where metadata URIs dont exist

Annotations
Annotations are properties that have a dot (.) in the name There are instance annotations and property annotations o Instance annotations belong to the object they appear in (e.g., odata.metadata, odata.count, etc.) o Property annotations belong to the property that is part of their name (e.g., Orders@odata.navigationlinkurl, etc.) Instance annotations are used when annotating a value that is a JSON object; property level annotations are used to annotate a value that is a primitive value or an array (in both cases there is no place to put the annotation inside the value). Property-level annotations are also used to provide annotations for values that are not present in the payload (e.g., there is no JSON property for a navigation property in the payload; instead the navigation link is specified via a property annotation). All annotations that start with odata. are reserved for future extensions of the protocol and format Custom annotations are annotations that have a non-empty prefix that is different from odata.. Custom annotations are currently ignored when reading payloads.

What annotations are used for


odata.metadata specifies the metadata URI for the payload odata.type specifies the type of the payload (or part of the payload). This is used to specify the type of o an entity if it is more derived than the type specified in the metadata URL. The annotation is inside the entity in this case. In the sample below the first entry in a feed of customers is of the more derived type NorthwindModel.PreferredCustomer ; other entries in the feed that dont have an explicit odata.type annotation are assumed to be of type NorthwindModel.Customer (the base type of the Customers entity set).

{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.NorthwindEntities/Customers" "value": [ { "odata.type": "NorthwindModel.PreferredCustomer", "CustomerID": "ALFKI", "CompanyName": "Alfreds Futterkiste", ... }, ...

12 | P a g e

JSON Light At A Glance


], }

March 31, 2012

an open property. The annotation is a property annotation for open primitive and collection properties and an instance annotation inside a complex property value. The sample below shows an open property OpenAge of type Edm.Int32 where the type is specified via a property annotation.

{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.NorthwindEntities/Customers(ALFKI)/OpenAge", "value@odata.type": "Edm.Int32" "value": 42 }

odata.count and odata.nextLink are used to annotate

o a feed (at the top-level or inside an expanded collection property) o a collection of entity reference links ($links response) at the top level See the sample in Section FEED above. The rest of the odata.* annotations are used to provide control information for an entry. Note that all of the control information for an entry is usually computed from metadata expressions and thus not present in the payload. odata.* annotations can be present in the payload to override the metadata expression evaluation in the case of exceptions to them (e.g., a custom edit link). o Instance annotations are used for the ID, ETag, read link, edit link, media read link, media edit link, media content type, media ETag, actions and functions of an entry. o Property annotations are used to describe the navigation and association links of a property, the read link, edit link, content type and ETag of a named stream The amount of control information in the payload can also be controlled by the $metadata query option. See Section CONTROLLING THE AMOUNT OF CONTROL INFORMATION IN THE PAYLOAD for more details. An example that shows all the OData instance and property annotations in the payload, i.e., if none of the control information would be computed from metadata expressions, is shown in Section $METADATA=ALL.

Annotation Groups
Annotation groups are a way to group multiple instance and/or property annotations into a named group that can be reused throughout the payload. Annotation groups are useful to further reduce the size of the payload when the same set of annotations appears repeatedly in a payload. The typical scenario when this happens is when a feed contains entries with open entity types and the same set of open (i.e., undeclared) properties appears in multiple or all of the entries in the feed. For each open property, a property annotation is used to describe its type. Without annotation groups these property 13 | P a g e

JSON Light At A Glance

March 31, 2012

annotations would have to appear in every entry of a feed; annotation groups provide a way to declare these property annotations only once and then reference them.
{ "odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.NorthwindEntities/OpenCustomers" "value": [ { "odata.annotationgroup": { "name": "openpropertytypes", "OpenAddress@odata.type": "Edm.String", "OpenPhone@odata.type": "Edm.Int32", }, "CustomerID": "ALFKI", "CompanyName": "Alfreds Futterkiste", "OpenAddress": "Obere Str. 57, 12209 Berlin, Germany", "OpenPhone": 0074321, ... }, { "odata.annotationgroupref": "openpropertytypes" "CustomerID": "ANTON", "CompanyName": "Antonio Moreno", "OpenAddress": "Mataderos 2312, 05023 Mxico D.F., Mexico", "OpenPhone": 5553932, ... }, ... ], }

Annotation groups are a syntactic grouping construct only; they do not introduce any new semantic meaning. The semantics of the annotation group is the same as if the annotations in the group would be inlined directly inside the owning object. The advantage is that instead of having to repeat the annotations in each entry of a feed, only the first entry defines the annotation group, the other entries simply reference it by name. Note that the declaration of an annotation group also applies the annotation group to the declaring object; thus there is no reference to the annotation group in the entry that declares it. On the other hand that means that an annotation group can only be introduced in an object that also applies it (and not as stand-alone construct at the beginning of the feed or always inside the first entry). Annotation groups and annotation group references have to be the first property in an object; in top-level objects, annotation groups and annotation group references appear after the odata.metadata annotation (and thus are the objects second property).

14 | P a g e

JSON Light At A Glance

March 31, 2012

Controlling the amount of control information in the payload


The amount of control information needed (or desired) in the payload depends on the client application and device. A new query option that can be used in the query URL of an OData request enables the client application to influence how much control information will be included in the payload. If a client favors computing control information over payload size, the $metadata=default (which can also be omitted from the URL) is the way to go. On devices where compute is expensive (in cost, battery life, etc.) or where the client application is not capable of computing control information, $metadata=all provides a way to inline all the control information that normally would be computed from metadata expressions in the payload. $metadata=none is an option for clients that have out-ofband knowledge of the expected payload kind and type and thus dont need any control information.

$metadata=default
The default $metadata query option does not have to be included in the request URL and will be assumed if no other $metadata query option is present in the URL. It indicates that the server should use metadata expressions (to the extent the server supports them) to reduce the payload size. The response payload should also contain the odata.metadata annotation, the odata.nextLink and the odata.count annotations. Note that more odata.* annotations will appear in the payload if their values are not the same as the ones computed from metadata expressions (or the server does not support metadata expressions) and have to be treated as exceptions.

$metadata=none
When the client specifies that no control information should be included in the payload, it is assumed that the client has out-of-band knowledge of the payload kind and data types in the payload (or does not care). In this case, the odata.metadata URL is omitted from the payload otherwise the same set of control information as in the default option is present in the payload (including odata.nextLink and odata.count annotations as well as exceptions to the values that would be computed from metadata expressions.)

$metadata=all
In cases where the client is not capable of computing control information from metadata expressions or favors larger payload size over the additional computational requirements, $metadata=all tells the server to compute the metadata expressions on the server and include the control information explicitly in the payload. This, of course, will re-introduce the redundancies and inefficiencies of the current JSON verbose format but is a way less capable or resource constrained clients to work with the JSON Light format. The sample below is a feed response payload where all the control information has been embedded in the payload. 15 | P a g e

JSON Light At A Glance


{

March 31, 2012

"odata.metadata": "http://northwind.odata.org/$metadata #NorthwindModel.NorthwindEntities/Customers", "odata.count": 42, "value": [ { "odata.id": "http://northwind.odata.org/Customers(ALFKI)" "odata.etag": "etag-value" "odata.readLink": "http://northwind.odata.org/read/Customers(ALFKI)" "odata.editLink": "http://northwind.odata.org/edit/Customers(ALFKI)" "odata.mediaReadLink": "http://northwind.odata.org/Customers(ALFKI)/Image" "odata.mediaEditLink": "http://northwind.odata.org/Customers(ALFKI)/$value" "odata.mediaETag": "stream-etag-value" "odata.mediaContentType": "image/jpg" "odata.actions": [ ... actions for this entry ...] "odata.function": [ ... functions for this entry ...] "VoiceMail@odata.mediareadLink": "http://.../Customers(ALFKI)/Voice" "VoiceMail@odata.mediaeditLink": "http://.../Customers(ALFKI)/Voice/$value" "VoiceMail@odata.mediaetag": "voice-etag-value" "VoiceMail@odata.mediacontentType": "audio/basic" "Orders@odata.navigationLinkUrl": "http://.../Customers(ALFKI)/Orders" "Orders@odata.associationLinkUrl": "http://.../Customers(ALFKI)/OrdersRel" "CustomerID": "ALFKI", "CompanyName": "Alfreds Futterkiste", "OpenAddress@odata.type": "Edm.String" "OpenAddress": "Obere Str. 57, 12209 Berlin, Germany", ... }, ... ], "odata.nextLink": "http://northwind.odata.org/next(123122)" }

odata.metadata: the metadata URI of the payload. odata.count: the inline count of a feed or collection of entity reference links. odata.nextLink: the next link of a feed or collection of entity reference links. odata.id: the ID of the entry. odata.etag: the ETag of the entry. odata.readLink: the link used to read the entry. odata.editLink: the link used to edit/update the entry. odata.mediaReadLink: the link used to read the default stream of an MR/MLE entry. odata.mediaEditLink: the link used to edit/update the default stream of an MR/MLE entry. odata.mediaETag: the ETag of the default stream of an MR/MLE entry. odata.mediaContentType: the content type of the default stream of an MR/MLE entry.

16 | P a g e

JSON Light At A Glance


odata.actions: the array of actions specified for the entry. odata.functions: the array of functions specified for the entry.

March 31, 2012

VoiceMail@odata.mediaReadLink: the link used to read the stream of the VoiceMail named

stream property.
VoiceMail@odata.mediaEditLink: the link used to edit/update the stream of the VoiceMail

named stream property.


VoiceMail@odata.mediaETag: the ETag of the VoiceMail named stream property. VoiceMail@odata.mediaContentType: the content type of the VoiceMail named stream

property.
Orders@odata.navigationLinkUrl: the link used to retrieve the values of the Orders

navigation property.
Orders@odata.associationLinkUrl: the link used to describe the relationship between the

customer instance and its orders. OpenAddress@odata.type: the type name of the open property OpenAddress.

Content Type and Payload Ordering Constraints


A Json Light request or response payload has a content type of application/json;odata=light . Starting in V3 of the OData protocol, the content type application/json (without any parameters) will also be interpreted as Json Light payload. In previous versions the application/json content type means the verbose JSON format. The verbose JSON format is supported in V3 through the application/json;odata=verbose content type. As mentioned at the beginning of this document, one of the design goals of JSON Light was to support streaming scenarios where only ever a single entry can be assumed to fit into memory. To support streaming in JSON Light, some payload ordering constraints must be imposed. We realize, however, that some clients (and servers) will not be able to control the order of the JSON properties in the payload or might not care about streaming at all. As a result, the payload ordering constraints described in the rest of this section are not mandatory for JSON Light. Processors can only assume streaming support if it is explicitly indicated in the content type via the streaming=true parameter. A payload with content type application/json;odata=light;streaming=true can thus be assumed to support streaming whereas a payload with content type application/json;odata=light cannot. JSON Light producers are encouraged to follow the payload ordering constraints whenever possible (and specify the streaming=true content type parameter) to support the maximum set of client scenarios. To support streaming scenarios the following payload ordering constraints have to be met: If present, the odata.metadata annotation has to be the first property in a response payload o Request payloads do not have an odata.metadata annotation Annotation groups must come immediately after the odata.metadata annotation The odata.type annotation must appear next in the payload.

17 | P a g e

JSON Light At A Glance

March 31, 2012

The odata.id and odata.etag annotations must appear before any property or property annotation. All property annotations for property SomeProperty have to appear as a group immediately before the property itself. Note that the one exception to this rule is the SomeProperty@odata.nextlink annotation of an expanded collection navigation property; the next link can oftentimes only be computed after all the entries in a feed have been written and thus is allowed to appear after the SomeProperty property. All other odata.* annotations can appear anywhere in the payload (as long as they are not violating any of the above rules).

Metadata Expressions
Metadata expressions are specified in the metadata document (returned from the $metadata endpoint of an OData service) using CSDL annotations. The metadata expressions represent instructions how to compute parts of the OData control information for an entry. When reading an OData payload, these expressions are then used to compute control information that has been omitted from the payload. They are also used to guide a URI builder when producing request URLs for a query. As a result, the metadata expressions give you a way to completely customize the URI scheme you use with your service. This section first gives an overview of how CSDL annotations are represented in the metadata document and then focuses on the OData metadata expressions themselves.

CSDL Annotations
Metadata expressions are encoded in the metadata document as CSDL annotations. Such annotations have a target that describes what part of the metadata they apply to (e.g., an entity set or an entity container or an entity type). A qualifier supports further specifying what part of the target the annotation should be applied to (e.g., the target of an annotation might be an entity type and the qualifier would specify a particular property within this entity type). Once the target is identified, the annotation has a term that allows us to annotate a target with multiple annotations for different purposes using different terms. Finally the annotation has a value or an expression body. Here is the general structure of a CSDL annotation (more details about CSLD annotations can be found in the CSDL spec (TODO: add reference)).
<Annotations Target="{annotation-target}"> <ValueAnnotation Term="{term}" Qualifier="{qualifier}" String="{string-value}" /> <ValueAnnotation Term="{term}" Qualifier="{qualifier}"> {expression-body} </ValueAnnotation> </Annotations>

OData Metadata Expressions


OData specifies a set of annotations that are used to compute control information for the payload. These annotations have differing targets and are outlined below: 18 | P a g e

JSON Light At A Glance Entity container target

March 31, 2012

odata.expression.baseUri: the base URI for all the URIs built for the entity container specified

in as the target. If this annotation is not specified, the metadata URI of the service is used as a base URI. Entity set target
odata.expression.entitySetUri: the relative or absolute URI for the annotated entity set. odata.expression.entityInstanceUri: the relative or absolute URI for an entity instance of

the annotated entity set.


odata.expression.navigationLinkUri: the relative or absolute URI for the navigation link

(specified in the qualifier) of an entity instance of the annotated entity set. odata.expression.associationLinkUri: the relative or absolute URI for the association link (specified in the qualifier) of an entity instance of the annotated entity set. odata.expression.id: the ID of an entity instance of the annotated entity set. odata.expression.etag: the ETag of an entity instance of the annotated entity set. odata.expression.operationTargetUri: the target URI of an operation (action or function) for an entity instance of the annotated entity set. odata.expression.operationTitle: the title of an operation (action or function) for an entity instance of the annotated entity set odata.expression.mediaReadLinkUri: the relative or absolute URI for the read link of the stream property (specified in the qualifier) of an entity instance of the annotated entity set. If the qualifier is left empty, the annotation applies to the default stream of an MLE/MR entry. odata.expression.mediaEditLinkUri: the relative or absolute URI for the edit link of the stream property (specified in the qualifier) of an entity instance of the annotated entity set. If the qualifier is left empty, the annotation applies to the default stream of an MLE/MR entry. odata.expression.mediaETag: the ETag of the stream property (specified in the qualifier) of an entity instance of the annotated entity set. If the qualifier is left empty, the annotation applies to the default stream of an MLE/MR entry. odata.expression.mediaContentType: the content type of the stream property (specified in the qualifier) of an entity instance of the annotated entity set. If the qualifier is left empty, the annotation applies to the default stream of an MLE/MR entry.

Here is a sample of the annotations for the Customers entity set needed to compute the navigation link URI of the Orders navigation property.
<Annotations Target="NorthwindModel.NorthwindEntities"> <ValueAnnotation Term="odata.expression.baseUri" String="http://northwind.odata.org/" /> </Annotations> <Annotations Target="NorthwindModel.NorthwindEntities/Customers"> <ValueAnnotation Term="odata.expression.entitySetUri" String="Customers/" /> <ValueAnnotation Term="odata.expression.entityInstanceUri"> <Apply Function="odata.stringConcat">

19 | P a g e

JSON Light At A Glance

March 31, 2012

<Apply Function="odata.toRawLiteral"> <Path>ID</Path> </Apply> <String>/</String> </Apply> </ValueAnnotation> <ValueAnnotation Term="odata.expression.navigationLinkUri" Qualifier="Orders" String="Orders/"> </Annotations>

You will note that this is not a single expression for the navigation link URI but instead a set of expressions that will be combined to produce the actual navigation link URI. The reason for that is that when creating request URIs we need to be able to recursively follow navigation links and thus composability of the expressions is a must. How the composition works (based on the sample expressions above) will be shown in the next section. Also note that when no expressions are specified in the metadata document, the WCF Data Services default expressions are assumed. Similarly, when only a select few expressions are specified in the metadata document, the default expressions will be used for the non-specified targets. For cases where this behavior is undesired, a new query option is introduced that will control whether default expressions should be assumed or not. The query option (in spirit) will be $useDefaultExpressions=true|false but the actual naming and allowed values are still being discussed.

Metadata Expression Composition Rules


As listed in $METADATA=ALL, there is a set of odata.* instance and property annotations that we need to be able to create from the annotations in the metadata document. The following table lists these OData annotations again and shows how they are computed from the metadata expressions listed above. A general rule that applies to all composition of expression values is that once we hit an absolute URI we stop composing. That way some of the expressions can opt-out of the composition rules and specify the full URI value themselves. In the table below we use the & operator to denote composition of two expression values. More details about the & operator follow later in this section.

Computed Value

Composition rule
(values in curly braces are results from other expressions, i.e., {odata.editLink} is the result )

odata.id odata.etag odata.readLink

odata.expression.id odata.expression.etag odata.expression.baseUri & odata.expression.entitySetUri & odata.expression.entityInstanceUri (TODO: fix this composition) odata.expression.baseUri &

odata.editLink

20 | P a g e

JSON Light At A Glance

March 31, 2012

odata.expression.entitySetUri & odata.expression.entityInstanceUri


odata.mediaReadLink odata.mediaEditLink odata.mediaETag odata.mediaContentType

{odata.editLink} & odata.expression.mediaReadLinkUri [no qualifier] {odata.editLink} & odata.expression.mediaEditLinkUri [no qualifier] odata.expression.mediaETag [no qualifier] odata.expression.mediaContentType [no qualifier]

<named-stream>@odata.mediaReadLink <named-stream>@odata.mediaEditLink <named-stream>@odata.mediaETag <named-stream>@odata.mediaContentType

{odata.editLink} & odata.expression.mediaReadLinkUri [<named-stream> qualifier] {odata.editLink} & odata.expression.mediaEditLinkUri [<named-stream> qualifier] odata.expression.mediaETag [<named-stream> qualifier] odata.expression.mediaContentType [<named-stream> qualifier]

<nav-prop>@odata.navigationLinkUrl <nav-prop>@odata.associationLinkUrl

{odata.editLink} & odata.expression.navigationLinkUri [<nav-prop> qualifier] {odata.editLink} & odata.expression.associationLinkUri [<nav-prop> qualifier]

<action-or-function> title <action-or-function> target

odata.expression.operationTitle [qualifier is the name of the action or function] {odata.editLink} & odata.expression.operationTargetUri [qualifier is the name of the action or function]

Combinator Functions
This section explains some details around the & operator used in the previous section to combine values computed from metadata expressions to form a full URI. In general and if no combinatory function is specified in the expression we use standard URI composition rules and thus treat the values created from metadata expressions as relative URIs. For some URI schemes, however, this does not work and so two more combinatory functions can be used to change how the values are combined. To make the different behaviors of the combinator functions more obvious, we use an example of an entity set URI http://northwind.odata.org/Customers and a relative entity instance URI (1). 21 | P a g e

JSON Light At A Glance

March 31, 2012

URI composition: the default combinatory function (that can be omitted from the payload). Follows standard URI composition rules. o Composition result: http://northwind.odata.org/(1) o Since the Customers segment is not terminated in a /, URI composition rules will replace the last segment with (1). String concatenation: treats the values generated from the metadata expressions as strings and simply concatenates them. o Composition result: http://northwind.odata.org/Customers(1) AddSegment: a combinator function that expresses that the value computed from the metadata expression should be added as a new URI segment to the URI created so far. o Composition result: http://northwind.odata.org/Customers/(1) o Since the Customers segment is not terminated in a/, the AddSegment composition will first append a / (if none exists) and then apply URI composition rules.

Here is how the combinatory function is specified for a metadata expression; it is an annotation on the annotation.
<Annotations Target="NorthwindModel.NorthwindEntities"> <ValueAnnotation Term="odata.expression.baseUri" String="http://northwind.odata.org/" /> </Annotations> <Annotations Target="NorthwindModel.NorthwindEntities/Customers"> <ValueAnnotation Term="odata.expression.entitySetUri" String="Customers/" /> <ValueAnnotation Term="odata.expression.entityInstanceUri"> <ValueAnnotation Term="odata.combinator" String="StringConcat" /> <Apply Function="odata.toRawLiteral"> <Path>ID</Path> </Apply> </ValueAnnotation> <ValueAnnotation Term="odata.expression.navigationLinkUri" Qualifier="Orders" String="Orders/"> <ValueAnnotation Term="odata.combinator" String="AddSegment" /> </ValueAnnotation> </Annotations>

Functions in Metadata Expressions


A few functions can be used when creating the metadata expressions for the various annotations:
odata.toUriLiteral: converts the value of its argument to a literal form suitable for use in

URIs.
odata.toRawLiteral: converts the value of its argument to its raw from. odata.getTypeName: gets the type name of the current entry. odata.stringConcat: concatenates multiple strings.

Functions are used with an <Apply> expression as shown in the sample above.

22 | P a g e

JSON Light At A Glance

March 31, 2012

Conclusion
In closing, please remember that this is an introductory document and by no means exhaustive. It has no normative character whatsoever and some things are likely going to change as we progress in our designs and implementations. If you got a better idea what the JSON Light format for OData is all about and what overall direction we are taking, this document has served its purpose. For more details, questions, feedback or comments please contact odatateam@microsoft.com.

23 | P a g e

Vous aimerez peut-être aussi