Professional Documents
Culture Documents
Json Overview 2012-11-08
Json Overview 2012-11-08
CONTENTS
Introducing the New JSON Format......................................................................................3
Motivation...........................................................................................................................3
JSON Format Design............................................................................................................3
Response payload samples.................................................................................................5
Entry................................................................................................................................5
Feed.................................................................................................................................6
Property...........................................................................................................................7
Entry with expanded navigation links.............................................................................8
Service document............................................................................................................9
Entity reference links.....................................................................................................10
Top-level (streaming) collections...................................................................................11
Error...............................................................................................................................12
Request payload samples.................................................................................................13
Entry..............................................................................................................................13
Entry with deep inserts..................................................................................................13
Entry with binding operations (insert or update)..........................................................14
Property.........................................................................................................................15
Entity reference links.....................................................................................................15
Parameters....................................................................................................................15
The Metadata URL.............................................................................................................17
Relative URLs....................................................................................................................18
Null Payloads.....................................................................................................................19
Annotations.......................................................................................................................19
Well-known annotations................................................................................................20
Controlling the amount of control information in the payload..........................................20
odata=minimalmetadata...............................................................................................21
odata=fullmetadata......................................................................................................21
odata=nometadata.......................................................................................................22
Heuristically Detectable Primitive Types...........................................................................22
Content Type and Payload Ordering Constraints..............................................................23
Metadata Expressions.......................................................................................................24
1
MOTIVATION
Prior to OData v3, the OData protocol had two supported serialization formats a format
based on AtomPub and a different JSON format (referred to hereafter as JSON Verbose).
Each of these formats assumed the control data (that is, the metadata that powers
much of OData) must be included on the wire. This resulted in two fundamental
problems:
1. Payload size. By design, AtomPub and JSON Verbose carry a significant amount of
metadata on the wire, increasing the payload size of requests and responses.
2. Ease-of-use for JavaScript processors:
Materializing objects from an AtomPub payload is not a trivial problem to solve
The increasing popularity of mobile devices and simple JavaScript clients has made it
more important than ever to have a serialization format that is both compact and trivial
to parse. These are the problems the new JSON format attempts to solve.
In order to make the new format easy to process by JavaScript clients, the only logical
conclusion is to continue to support a JSON format. Looking at current JSON Verbose and
AtomPub payloads, a significant amount of the payload is highly predictable (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). The key change in this format is to
remove all the predictable parts of the wire format from the actual payload. To
reconstitute this data on the receiving end, expressions are used to compute missing
links, type information, and other control data. These expressions (together with the
data on the wire) can be used by the client to recompute all the predictable payload
pieces as if they had been included on the wire directly.
The extensibility story of the new JSON format revolves around so-called annotations in
the payload. Annotations are used to add control information to a JSON 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.
Annotations are used in JSON to capture control information that cannot be predicted
(e.g., the next link of a feed) as well as to provide a mechanism to provide values where
a computed value would be wrong (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 opt for a larger payload size to avoid computational complexity; as a result
the Accept header allows the client to control the amount of control information included
on the wire.
To make JSON payloads support streaming scenarios, we put in place a few restrictions
with respect to the order in which data must appear on the wire. For details on the
ordering requirements, see Content Type and Payload Ordering Constraints
Entry
http://.../Soupon.svc/Soupons(1)/?$format=json
{
"odata.metadata": "http://.../Soupon.svc/$metadata#Soupons/@Element",
"#SouponContext.Buy": {},
"ID": 1,
"Name": "Rustic Italian Tortellini Soup",
"Description": "This is my favorite soup recipe. It's quick to fix on a busy night and full
of healthy, tasty ingredients. It originally called for spicy sausage links, but I've found that
turkey sausage, or even ground turkey breast, is just as good. \u2014Tracy Fasnacht, Irwin,
Pennsylvania",
"Price": "1.85754591173378",
"DealExpiresAt": "2012-10-06T02:21:16.4908996-07:00",
"ImageUrl": "http://.../pic.jpg",
"Rating": 5.0,
"NumberOfReviews": 46,
"Ingredients": ["3 Italian turkey sausage links (4 ounces each), casings removed", "1
medium onion, chopped", "6 garlic cloves, minced", "2 cans (14-1/2 ounces each) reducedsodium chicken broth", "1-3/4 cups water", "1 can (14-1/2 ounces) diced tomatoes,
undrained", "1 package (9 ounces) refrigerated cheese tortellini", "1 package (6 ounces)
fresh baby spinach, coarsely chopped", "2-1/4 teaspoons minced fresh basil or 3/4 teaspoon
dried basil", "1/4 teaspoon pepper", "Dash crushed red pepper flakes", "Shredded Parmesan
cheese, optional"],
"Category": "Soup"
}
Comments:
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
5
http://.../Soupon.svc/Users/?$inlinecount=allpages&$format=json
{
"odata.metadata": "http://.../Soupon.svc/$metadata#Users",
"odata.count": "11",
"value": [{
"UserID": "pilack",
"DisplayName": "Pilar Ackerman",
"JoinedAt": "2010-11-30T11:51:21.2265317-07:00",
"LastSeenAt": "2012-09-11T11:51:21.2265317-07:00",
"BillingAddress": {
"Line1": "12345 Grant Street",
"Line2": null,
"City": "Taft",
"State": "Ohio",
"ZipCode": "98052"
},
"FavoriteTags": ["gazpacho", "tomato", "vegetarian"]
},
... ],
"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 results are always
o
wrapper is needed.
This payload reflects some of the ordering necessary for streaming feeds:
o odata.metadata appears first in the payload.
o odata.nextLink appears last in the payload.
BillingAddress is a complex property that appears as a normal JSON object.
Property
http://.../Soupon.svc/Users('pilack')/DisplayName?$format=json
{
"odata.metadata": "http://.../Soupon.svc/$metadata#Edm.String",
"value": "Pilar Ackerman"
}
http://.../Soupon.svc/Users('pilack')/FavoriteTags?$format=json
{
"odata.metadata": "http://.../Soupon.svc/$metadata#Collection(Edm.String)",
"value": ["gazpacho", "tomato", "vegetarian"]
}
http://.../Soupon.svc/Users('pilack')/BillingAddress?$format=json
{
"odata.metadata": "http://.../Soupon.svc/$metadata#Soupon.BillingAddress",
"Line1": "12345 Grant Street",
"Line2": null,
"City": "Taft",
"State": "Ohio",
"ZipCode": "98052"
}
Comments:
Comments:
property.
In some OData servers, expanded navigation properties tend to appear before
Service document
http://.../Soupon.svc/?$format=json
{
"odata.metadata": "http://.../Soupon.svc/$metadata",
"value": [{
"name": "Soupons",
"url": "Soupons"
}, {
"name": "Users",
"url": "Users"
}
]
Comments:
The service document contains an array of JSON objects that represent the entity
sets.
Each JSON object contains the name of the entity set as well as its URL (either
absolute or relative to the odata.metadata URL).
http://.../Soupon.svc/Users('pilack')/$links/PurchasedSoupons/
{
"odata.metadata": "http://.../Soupon.svc/$metadata
#Users/$links/PurchasedSoupons",
"value": [{
"url": "Soupons(11)"
}, {
"url": "Soupons(1)"
}
]
}
http://.../Soupon.svc/Users('pilack')/$links/PurchasedSoupons(1)/
{
"odata.metadata": "http://.../Soupon.svc/$metadata
#Users/$links/PurchasedSoupons/@Element",
"url": "Soupons(1)"
Comments:
10
Comments:
11
Error
http://.../Soupon.svc/Users?$format=json&$badqueryoption=true
{
"error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The query parameter '$badqueryoption' begins with a systemreserved '$' character but is not recognized."
}
}
}
Comments:
12
Entry
{
"BillingAddress": {
"City": "Clinton",
"Line1": "23456 Cleveland St",
"Line2": null,
"State": "TX",
"ZipCode": "98052"
},
"DisplayName": "David Hamilton",
"FavoriteTags": [],
"JoinedAt": "2012-10-05T14:14:43.1229977-07:00",
"LastSeenAt": "2012-10-05T14:14:43.1269991-07:00",
"UserID": "davham"
Comments:
"ReferredBy": {
"BillingAddress": {
"City": "Polk",
"Line1": "23456 Taylor St",
"Line2": null,
"State": "NV",
"ZipCode": "98052"
},
"DisplayName": "Sanjay Patel",
"FavoriteTags": [],
"JoinedAt": "2012-10-03T18:14:43.1229977-07:00",
"LastSeenAt": "2012-10-03T20:14:43.1269991-07:00",
"UserID": "sanpat"
},
"BillingAddress": {
"City": "Clinton",
13
Comments:
The above payload can be used when inserting a new order and at the same time
"ReferredBy@odata.bind": "http://./Soupon.svc/Users('haoche')",
"BillingAddress": {
"City": "Clinton",
"Line1": "23456 Cleveland St",
"Line2": null,
"State": "TX",
"ZipCode": "98052"
},
"DisplayName": "David Hamilton",
"FavoriteTags": [],
"JoinedAt": "2012-10-05T14:14:43.1229977-07:00",
"LastSeenAt": "2012-10-05T14:14:43.1269991-07:00",
"UserID": "davham"
Comments:
payload.
In update scenarios, only bind operations but not deep inserts are allowed.
Property
{
14
}
{
"City": "Polk",
"Line1": "23456 Taylor St",
"Line2": null,
"State": "NV",
"ZipCode": "98052"
}
{
}
Comments:
"url": "http://.../Soupon.svc/Users('pilack')"
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:
15
syntax
Sample URL
Metadata URL for sample
Comments (Optional)
{metadata-url}#{entity-set}
http://.../Soupon.svc/Soupons
http://.../Soupon.svc/$metadata#Soupons
If the entity set is in an entity container that has the
IsDefaultEntityContainer attribute set to true, the entity set may be
unqualified. If the entity set is in an entity container that has no
IsDefaultEntityContainer attribute (or the value of the attribute is false),
the entity set must be namespace and container qualified.
Feed of
Derived
Elements
Element
{metadata-url}#{entity-set}/{type-cast}
http://.../Soupon.svc/Soupons/Soupon.FeaturedSoupon
http://.../Soupon.svc/$metadata#Soupons/Soupon.FeaturedSoupon
If a feed consists exclusively of derived elements, a type cast segment is
added to the metadata URL.
{metadata-url}#{entity-set}/@Element
http://.../Soupon.svc/Soupons(1)
http://.../Soupon.svc/$metadata#Soupons/@Element
If a response is guaranteed to contain only a single entry from a feed,
/@Element is appended to the metadata URL. This is also true for links
payloads.
Derived
Element
{metadata-url}#{entity-set}/{type-cast}/@Element
http://.../Soupon.svc/Soupons(1)/Soupon.FeaturedSoupon
http://.../Soupon.svc/
$metadata#Soupons/Soupon.FeaturedSoupon/@Element
If a response is guaranteed to contain only a single element of a derived
type, /<Type>/@Element is appended to the metadata URL.
Complex
16
{metadata-url}#{namespace}.{type-name}
or
Primitive
Type
Property
Collectio
n Type
Property
Null
http://.../Soupon.svc/Soupons(1)/Name
http://.../Soupon.svc/$metadata#Edm.String
If a response is a complex type or primitive type, the metadata URL
contains the fully qualified type of the property.
{metadata-url}#Collection({namespace}.{type-name})
http://.../Soupon.svc/Soupons(1)/Tags
http://.../Soupon.svc/$metadata#Collection(Edm.String)
If a response is a collection of complex types or primitive types, the
metadata URL names the type of the property.
{metadata-url}#Edm.Null
http://.../Soupon.svc/Soupons(1)/Description
http://.../Soupon.svc/$metadata#Edm.Null
If a response is a null collection, complex or primitive type property, the
metadata URL fragment is simply Edm.Null.
Operatio
n Result
{metadata-url}#{entity-set-or-type-name}
http://.../Soupon.svc/GetTopFiveCustomers
http://.../Soupon.svc/$metadata#Users
A response from an operation (service operation, action, function) has a
metadata URL that identifies the type returned by the operation. The
metadata URL will correspond to one of the former examples.
Service
Doc
Entity
Referenc
e Links
{metadata-url}
http://.../Soupon.svc/
http://.../Soupon.svc/$metadata
{metadata-url}#{entity-set}/$links/{nav-prop}[/@Element]
http://.../Soupon.svc/Users('pilack')/$links/PurchasedSoupons(1)
http://.../Soupon.svc/$metadata
#Users/$links/PurchasedSoupons/@Element
If a response is guaranteed to contain only a single element from a
navigation property with cardinality of many, /@Element is appended to
the metadata URL.
RELATIVE URLS
As noted previously, a significant amount of the payload for AtomPub and JSON Verbose
has to do with redundant data. This redundant data frequently manifests in the format of
very similar URLs. One benefit of the metadata URL is that, when present, the metadata
URL provides a consistent base for expanding relative URLs into absolute URLs.
As a general rule, whenever the metadata URL is present in a payload (whether request
or response), the URLs in the payload are allowed to be represented as relative URLs.
17
The processor expanding the URLs should use normal URL expansion rules and use the
metadata URL as a base.
NULL PAYLOADS
An attempt to access or update a collection, complex or primitive type property may
require a null payload. (Note: this is not true of an attempt to access an entity type
property, as there is no concept of null for entity types the result would simply be a
404 Not Found.) In all cases, the null payload is represented as follows:
{
}
"odata.metadata":"http://.../Soupon.svc/$metadata#Edm.Null"
A null payload is the only request payload that requires the metadata URL to be
included in the body of the request. This is because an empty string is not valid JSON,
and a payload that consisted merely of the object begin and end braces would indicate
that all properties on the object should be reset to their defaults.
ANNOTATIONS
Annotations are an extensibility mechanism that allow servers and clients to include
information other than the raw data in the request or response. Annotations are used to
include control information in many payloads. For example, the odata.metadata
annotation is included in almost all payloads.
Annotations are easily identifiable as properties that have a dot ('.') in the name
of the property.
There are two types of annotations:
o Instance annotations annotate the object that contains the annotation
o
<property>@<annotation>.
Instance annotations are commonly used when annotating a value that is a JSON
annotation).
All annotations that start with 'odata.' are reserved for future extensions of the
18
Well-known annotations
There are a number of annotations that are commonly seen in OData payloads.
functions of an entry.
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 via the
Accept header.
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 available in odata=fullmetadata.
information, odata=fullmetadata directs the server to inline the control information that
normally would be computed from metadata expressions in the payload.
odata=nometadata is an option for clients that have out-of-band knowledge of the
expected payload kind and type and thus don't need any control information.
odata=minimalmetadata
odata=minimalmetadata is the default value for the odata parameter and will be
The type is derived from the type specified for the feed
The type is for an open property
Note that more odata.* annotations will appear in the payload if their actual values are
not the same as the computed values (or the server is incapable of removing them).
When odata.* annotations appear in the payload, they must be treated as exceptions.
odata=fullmetadata
In cases where the client is incapable of or unwilling to compute control information,
odata=fullmetadata instructs the server to include all control information explicitly in the
payload. This, of course, will reintroduce some of the redundancies and inefficiencies of
the JSON Verbose format but is a way less capable or resource constrained clients can
work with the new JSON format.
Note that it is very important for servers to respect this value of the odata parameter. If
a client requests full metadata but only gets back minimal metadata, it is quite possible
that the client will not accurately interpret the response.
The full list of annotations that may appear in an odata=fullmetadata response are as
follows:
20
entry.
odata.mediaETag: the ETag of the default stream of an MR/MLE entry.
entry.
odata.actions: the array of actions specified for the entry. * TODO: This is out of
date.
odata.functions: the array of functions specified for the entry. * TODO: This is out
of date.
odata.navigationLinkUrl: the link used to retrieve the values of a navigation
property.
odata.associationLinkUrl: the link used to describe the relationship between this
odata=nometadata
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 annotation is
omitted from the payload otherwise the same set of control information as in the
default option is present in the payload (including the odata.nextLink and count
annotations as well as exceptions to the values that would be computed from metadata
expressions.)
Integral values have a first class representation in JSON and do not need any
additional annotations. If the value of a property is represented as a number
without a . embedded, the type should be interpreted as an integral value.
(Note: Int64 values are represented as strings due to the fact that JavaScript
additional annotations.
String values do have a first class representation in JSON, but there is an obvious
collision: OData also encodes a number of other primitive types as strings, e.g.
DateTime, Int64, etc. In this case, we are able to apply a simple process-of-
21
OData protocol, the content type application/json (without any parameters) will be
interpreted as application/json;odata=minimalmetadata. In previous versions the
application/json content type meant the JSON Verbose format. The JSON Verbose format
follow the payload ordering constraints whenever possible (and include the
streaming=true content type parameter) to support the maximum set of client scenarios.
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.
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.
22
All other odata.* annotations can appear anywhere in the payload (as long as they
METADATA EXPRESSIONS
Metadata expressions are either specified in the metadata document (returned from the
$metadata endpoint of an OData service) using CSDL annotations or are derived from
well-known convention sets. 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 URL builder when producing
request URLs for a query. As a result, the metadata expressions give you a way to
completely customize the URL scheme you use with your service.
Fully customizable metadata expressions are a very desirable feature, however they are
not currently on the OData roadmap. There will be two sets of URL conventions initially
supported in the JSON format: the Default set and a set of conventions used for Azure.
24