From 36dc1d67235be46c7d0e3ec41ce5a2a8460468c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the A property or operation response that is of a primitive type is represented as an object with a single name/value pair, whose name is A property or operation response that is of complex type is represented as a complex value. A property or operation response that is of a collection type is represented as an object with a single name/value pair whose name is A single-valued property or operation response that has the A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is A property or operation response that is of complex type is represented as a complex value. If the value is A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is Example 31: Note: the context URL is optional in requests.10 Media Entity
11 Individual Property or Operation Response
null
value does not have a representation; see OData-Protocol.value
and whose value is a primitive value.value
. Its value is the JSON representation of a collection of complex type values or collection of primitive values.null
value and carries no control information or instance annotations does not have a representation; see OData-Protocol.value
and whose value is a primitive value or null
.null
, the JSON object consists of name/value pairs for the @context
and the control information and instance annotations only.value
. Its value is the JSON representation of a collection of complex type values or collection of primitive values.null
value accompanied by an instance annotation{
+"@context": "http://host/service/$metadata#Model.Address",
+ "@Core.Messages": [{
+ "code": "EPOSTCODE",
+ "message": "Could not resolve postcode XYZ",
+ "severity": "error"
+ }]
+ }
@@ -1334,17 +1345,17 @@ functions or actions are advertised in the object representing a single entity.
The nextLink
control information MUST be included in a response that represents a partial result.
Example 31:
-{
-"@context": "…",
- "@count": 37,
- "value": [
- { … },
- { … },
- { … }
- ],
- "@nextLink": "…?$skiptoken=342r89"
- }
Example 32:
+{
+"@context": "…",
+ "@count": 37,
+ "value": [
+ { … },
+ { … },
+ { … }
+ ],
+ "@nextLink": "…?$skiptoken=342r89"
+ }
A collection of entity references is represented as a collection of entities, with entity reference representations instead of entity representations as items in the array value of the value
name/value pair.
The outermost JSON object in a response MUST contain a context
control information and MAY contain count
, nextLink
, or deltaLink
control information.
Example 32: entity reference to order 10643
-{
-"@context": "http://host/service/$metadata#$ref",
- "@id": "Orders(10643)"
- }
Example 33: entity reference to order 10643
+{
+"@context": "http://host/service/$metadata#$ref",
+ "@id": "Orders(10643)"
+ }
Example 33: collection of entity references
-{
-"@context": "http://host/service/$metadata#Collection($ref)",
- "value": [
- { "@id": "Orders(10643)" },
- { "@id": "Orders(10759)" }
- ]
- }
Example 34: collection of entity references
+{
+"@context": "http://host/service/$metadata#Collection($ref)",
+ "value": [
+ { "@id": "Orders(10643)" },
+ { "@id": "Orders(10759)" }
+ ]
+ }
If the delta response contains a partial list of changes, it MUST include a next link for the client to retrieve the next set of changes.
The last page of a delta response SHOULD contain a delta link in place of the next link for retrieving subsequent changes once the current set of changes has been applied to the initial set.
Example 34: a 4.01 delta response with three changes, in order of occurrence
-ContactName
for customer BOTTM
was changed to Susan Halvenstern
ANTON
was deletedContactName
for customer ALFKI
was changed to Blake Smithe
{
-"@context": "http://host/service/$metadata#Customers/$delta",
- "@count":3,
- "value": [
- {
- "@id": "Customers('BOTTM')",
- "ContactName": "Susan Halvenstern"
- },
- {
- "@removed": {
- "reason": "deleted"
- },
- "@id": "Customers('ANTON')"
- },
- {
- "@id": "Customers('ALFKI')",
- "ContactName": "Blake Smithe"
- }
- ],
- "@deltaLink": "Customers?$deltatoken=8015"
- }
Example 35: a 4.0 delta response with three changes, in order of occurrence
+Example 35: a 4.01 delta response with three changes, in order of occurrence
ContactName
for customer BOTTM
was changed to Susan Halvenstern
ANTON
was deletedContactName
for customer ALFKI
was changed to Blake Smithe
{
-"@odata.context": "http://host/service/$metadata#Customers/$delta",
- "@odata.count": 3,
+ "@context": "http://host/service/$metadata#Customers/$delta",
+ "@count":3,
"value": [
{
- "@odata.id": "Customers('BOTTM')",
- "ContactName": "Susan Halvenstern",
+ "@id": "Customers('BOTTM')",
+ "ContactName": "Susan Halvenstern"
},
{
- "@odata.context": "#Customers/$deletedEntity",
- "@odata.id": "Customers('ANTON')"
- },
- {
- "@odata.id": "Customers('ALFKI')",
- "ContactName": "Blake Smithe"
- }
- ],
- "@odata.deltaLink": "Customers?$deltatoken=8015"
- }
Example 36: a 4.0 delta response with three changes, in order of occurrence
+ContactName
for customer BOTTM
was changed to Susan Halvenstern
ANTON
was deletedContactName
for customer ALFKI
was changed to Blake Smithe
{
+"@odata.context": "http://host/service/$metadata#Customers/$delta",
+ "@odata.count": 3,
+ "value": [
+ {
+ "@odata.id": "Customers('BOTTM')",
+ "ContactName": "Susan Halvenstern",
+ },
+ {
+ "@odata.context": "#Customers/$deletedEntity",
+ "@odata.id": "Customers('ANTON')"
+ },
+ {
+ "@odata.id": "Customers('ALFKI')",
+ "ContactName": "Blake Smithe"
+ }
+ ],
+ "@odata.deltaLink": "Customers?$deltatoken=8015"
+ }
reason
— either deleted
, if the entity was deleted (destroyed), or changed
if the entity was removed from membership in the result (i.e., due to a data change).Example 36: deleted entity in OData 4.0 response — note that id
is a property, not control information
{
-"@context": "#Customers/$deletedEntity",
- "reason": "deleted",
- "id": "Customers('ANTON')"
- }
Example 37: deleted entity in OData 4.0 response — note that id
is a property, not control information
{
+"@context": "#Customers/$deletedEntity",
+ "reason": "deleted",
+ "id": "Customers('ANTON')"
+ }
In OData 4.01 payloads the deleted-entity object MUST include the following properties, regardless of the specified metadata
value. For ordered payloads, this control information MUST follow the payload ordering constraints.
For full metadata the context
control information MUST be included. It also MUST be included if the entity set of the deleted entity cannot be determined from the surrounding context.
The deleted-entity object MAY include additional properties of the entity, as well as annotations, and MAY include related entities, related deleted entities, or a delta or full representation of a related collection of entities, to represent related entities that have been modified or deleted.
Example 37: deleted entity in OData 4.01 response with id
control information (prefixed with an @
)
{
-"@context": "#Customers/$deletedEntity",
- "@removed": {
- "reason": "deleted",
- "@myannoation.deletedBy": "Mario"
- },
- "@id": "Customers('ANTON')"
- }
Example 38: deleted entity in OData 4.01 response with id
control information (prefixed with an @
)
{
+"@context": "#Customers/$deletedEntity",
+ "@removed": {
+ "reason": "deleted",
+ "@myannoation.deletedBy": "Mario"
+ },
+ "@id": "Customers('ANTON')"
+ }
Example 38: entity removed OData 4.01 response without id
control information and instead all key fields (ID
is the single key field of Customer
)
{
-"@removed": {},
- "ID": "ANTON"
- }
Example 39: entity removed OData 4.01 response without id
control information and instead all key fields (ID
is the single key field of Customer
)
{
+"@removed": {},
+ "ID": "ANTON"
+ }
If the expanded navigation property represents a delta, it MUST be represented as an array-valued control information delta
on the navigation property. Added/changed entities or entity references are added to the collection. Deleted entities in a nested delta representation represent entities no longer part of the collection. If the deleted entity specifies a reason
as deleted
, then the entity is both removed from the collection and deleted, otherwise it is removed from the collection and only deleted if the navigation property is a containment navigation property. The array MUST NOT contain added or deleted links.
Example 39: changes to related orders represented as a 4.01 nested delta representation
+Example 40: changes to related orders represented as a 4.01 nested delta representation
{
+"@context": "http://host/service/$metadata#Customers/$delta",
+ "@count":3,
+ "value": [
+ {
+ "@id": "Customers('ALFKI')",
+ "Orders@delta": [
+ {
+ "@removed": {
+ "reason": "changed"
+ },
+ "@id": "Orders(10643)"
+ },
+ {
+ "@id": "Orders(10645)",
+ "ShippingAddress": {
+ "Street": "23 Tsawassen Blvd.",
+ "City": "Tsawassen",
+ "Region": "BC",
+ "PostalCode": "T2F 8M4"
+ }
+ }
+ ]
+ },
+ {
+ "@removed": {
+ "reason": "deleted"
+ },
+ "@id": "Customers('ANTON')"
+ },
+ {
+ "@id": "Customers('ALFKI')",
+ "ContactName": "Blake Smithe"
+ }
+ ],
+ "@deltaLink": "Customers?$expand=Orders&$deltatoken=8015"
+ }
If the expanded navigation property is a full representation of the collection, it MUST be represented as an expanded navigation property, and its array value MUST represent the full set of entities related according to that relationship and satisfying any specified expand options, or a partial list containing a nextLink
. Following this chain of next links MUST eventually return the full set of entities related according to that relationship and satisfying any specified expand options; the final page does not include a delta link.
Members of the expanded navigation property MUST be represented as added/changed entities or entity references and MUST NOT include added links, deleted links, or deleted entities. Any entity not represented in the collection has either been removed, deleted, or changed such that it no longer satisfies the expand options in the defining query. In any case, clients SHOULD NOT receive additional notifications for such removed entities.
Example 40: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)
-{
-"@context": "http://host/service/$metadata#Customers/$entity/$delta",
- …
- "Orders@count": 42,
- "Orders": [ … ],
- "Orders@nextLink": "…",
- …
- "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
- }
Example 41: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)
+{
+"@context": "http://host/service/$metadata#Customers/$entity/$delta",
+ …
+ "Orders@count": 42,
+ "Orders": [ … ],
+ "Orders@nextLink": "…",
+ …
+ "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
+ }
context
control information specifies the entity set of the entity. This control information MUST be present for entities are not part of the entity set specified by the context URL, regardless of the specified metadata
value.
Example 41: changes to related orders represented as a 4.0 flattened delta payload
+Example 42: changes to related orders represented as a 4.0 flattened delta payload
ALFKI
ALFKI
{
-"@odata.context": "http://host/service/$metadata#Customers/$delta",
- "@odata.count": 5,
- "value": [
- {
- "@odata.context": "#Customers/$deletedLink",
- "source": "Customers('ALFKI')",
- "relationship": "Orders",
- "target": "Orders(10643)"
- },
- {
- "@odata.context": "#Customers/$link",
- "source": "Customers('BOTTM')",
- "relationship": "Orders",
- "target": "Orders(10645)"
- },
- {
- "@odata.context": "#Orders/$entity",
- "@odata.id": "Orders(10645)",
- "ShippingAddress": {
- "Street": "23 Tsawassen Blvd.",
- "City": "Tsawassen",
- "Region": "BC",
- "PostalCode": "T2F 8M4"
- }
- },
- {
- "@odata.context": "#Customers/$deletedEntity",
- "@odata.id": "Customers('ANTON')"
- },
- {
- "@odata.id": "Customers('ALFKI')",
- "ContactName": "Blake Smithe"
- }
- ],
- "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
- }
{
+"@odata.context": "http://host/service/$metadata#Customers/$delta",
+ "@odata.count": 5,
+ "value": [
+ {
+ "@odata.context": "#Customers/$deletedLink",
+ "source": "Customers('ALFKI')",
+ "relationship": "Orders",
+ "target": "Orders(10643)"
+ },
+ {
+ "@odata.context": "#Customers/$link",
+ "source": "Customers('BOTTM')",
+ "relationship": "Orders",
+ "target": "Orders(10645)"
+ },
+ {
+ "@odata.context": "#Orders/$entity",
+ "@odata.id": "Orders(10645)",
+ "ShippingAddress": {
+ "Street": "23 Tsawassen Blvd.",
+ "City": "Tsawassen",
+ "Region": "BC",
+ "PostalCode": "T2F 8M4"
+ }
+ },
+ {
+ "@odata.context": "#Customers/$deletedEntity",
+ "@odata.id": "Customers('ANTON')"
+ },
+ {
+ "@odata.id": "Customers('ALFKI')",
+ "ContactName": "Blake Smithe"
+ }
+ ],
+ "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
+ }
If a property of an entity is dependent upon the property of another entity within the expanded set of entities being tracked, then both the change to the dependent property as well as the change to the principal property or added/deleted link corresponding to the change to the dependent property are returned in the delta response.
The body of a PATCH
request to a URL identifying a collection of entities is a JSON object. It MUST contain the context
control information with a string value of #$delta
, and it MUST contain an array-valued property named value
containing all added, changed, or deleted entities. OData 4.0 delta payloads MAY additionally include added or deleted links between entities.
Example 42: 4.01 collection-update request for customers with expanded orders represented inline as a delta
+Example 43: 4.01 collection-update request for customers with expanded orders represented inline as a delta
EASTC
ContactName
of customer AROUT
ANATR
DUMON
PATCH /service/Customers HTTP/1.1
-Host: host
-Content-Type: application/json
-Content-Length: ###
-Prefer: return=minimal, continue-on-error
-
-{
-"@context": "#$delta",
- "value": [
- {
- "@Org.OData.Core.V1.ContentID": "1",
- "CustomerID": "EASTC",
- "CompanyName": "Eastern Connection",
- "ContactName": "Ann Devon",
- "ContactTitle": "Sales Agent"
- },
- {
- "@Org.OData.Core.V1.ContentID": "2",
- "CustomerID": "AROUT",
- "ContactName": "Thomas Hardy",
- },
- {
- "@Org.OData.Core.V1.ContentID": "3",
- "@removed": {
- "reason": "deleted"
- },
- "CustomerID": "ANTON"
- },
- {
- "@Org.OData.Core.V1.ContentID": "4",
- "CustomerID": "ALFKI",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "4.1",
- "OrderID": 11011,
- "CustomerID": "ALFKI",
- "EmployeeID": 3,
- "OrderDate": "1998-04-09T00:00:00Z",
- "RequiredDate": "1998-05-07T00:00:00Z",
- "ShippedDate": "1998-04-13T00:00:00Z"
- },
- {
- "@Org.OData.Core.V1.ContentID": "4.2",
- "@id": "Orders(10692)"
- },
- {
- "@Org.OData.Core.V1.ContentID": "4.3",
- "@id": "Orders(10835)",
- "RequiredDate": "1998-01-23T00:00:00Z",
- },
- {
- "@Org.OData.Core.V1.ContentID": "4.4",
- "@removed": {
- "reason": "changed"
- },
- "OrderID": 10643
- }
- ]
- },
- {
- "@Org.OData.Core.V1.ContentID": "5",
- "CustomerID": "ANATR",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "5.1",
- "OrderID": 10643
- }
- ],
- },
- {
- "@Org.OData.Core.V1.ContentID": "6",
- "CustomerID": "DUMON",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "6.1",
- "@removed": {
- "reason": "changed"
- },
- "OrderID": 10311
- }
- ]
- }
- ]
- }
PATCH /service/Customers HTTP/1.1
+Host: host
+Content-Type: application/json
+Content-Length: ###
+Prefer: return=minimal, continue-on-error
+
+{
+"@context": "#$delta",
+ "value": [
+ {
+ "@Org.OData.Core.V1.ContentID": "1",
+ "CustomerID": "EASTC",
+ "CompanyName": "Eastern Connection",
+ "ContactName": "Ann Devon",
+ "ContactTitle": "Sales Agent"
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "2",
+ "CustomerID": "AROUT",
+ "ContactName": "Thomas Hardy",
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "3",
+ "@removed": {
+ "reason": "deleted"
+ },
+ "CustomerID": "ANTON"
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4",
+ "CustomerID": "ALFKI",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "4.1",
+ "OrderID": 11011,
+ "CustomerID": "ALFKI",
+ "EmployeeID": 3,
+ "OrderDate": "1998-04-09T00:00:00Z",
+ "RequiredDate": "1998-05-07T00:00:00Z",
+ "ShippedDate": "1998-04-13T00:00:00Z"
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4.2",
+ "@id": "Orders(10692)"
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4.3",
+ "@id": "Orders(10835)",
+ "RequiredDate": "1998-01-23T00:00:00Z",
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4.4",
+ "@removed": {
+ "reason": "changed"
+ },
+ "OrderID": 10643
+ }
+ ]
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "5",
+ "CustomerID": "ANATR",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "5.1",
+ "OrderID": 10643
+ }
+ ],
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "6",
+ "CustomerID": "DUMON",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "6.1",
+ "@removed": {
+ "reason": "changed"
+ },
+ "OrderID": 10311
+ }
+ ]
+ }
+ ]
+ }
Assuming all changes can be applied without errors, the response would be
HTTP/1.1 204 No Content
Preference-Applied: return=minimal, continue-on-error
@@ -1786,124 +1797,124 @@ Add order 10643 to customer ‘ANATR’ - failed without further info
Remove order 10311 from customer ‘DUMON’ - failed without further info
-HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: ###
-Preference-Applied: return=minimal, continue-on-error
-
-{
-"@context": "#$delta",
- "value": [
- {
- "@Org.OData.Core.V1.ContentID": "1",
- "CustomerID": "EASTC",
- "@removed": {
- "reason": "changed"
- },
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "insert",
- "responseCode": 400,
- "info": {
- "code": "incmplt",
- "message": "Required field(s) not provided",
- "target": "Address",
- "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ],
- "severity": "error"
- }
- }
- },
- {
- "@Org.OData.Core.V1.ContentID": "2",
- "CustomerID": "AROUT",
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "update",
- "responseCode": 400,
- "info": {
- "code": "r-o",
- "message": "Customer is archived and cannot be changed",
- "severity": "error"
- }
- }
- },
- {
- "@Org.OData.Core.V1.ContentID": "3",
- "CustomerID": "ANTON",
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "delete",
- "responseCode": 400,
- "info": {
- "code": "ufo",
- "message": "Customer has unfinished orders and cannot be deleted",
- "severity": "error"
- }
- }
- },
- {
- "@Org.OData.Core.V1.ContentID": "4",
- "CustomerID": "ALFKI",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "4.3",
- "@id": "Orders(10835)",
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "update",
- "responseCode": 400,
- "info": {
- "code": "b/s",
- "message": "RequiredDate cannot be changed because Order is already being shipped",
- "severity": "error"
- }
- }
- }
- ]
- },
- {
- "@Org.OData.Core.V1.ContentID": "5",
- "CustomerID": "ANATR",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "5.1",
- "@removed": {
- "reason": "changed"
- },
- "OrderID": 10643,
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "link",
- "responseCode": 404,
- "info": null
- }
- }
- ]
- },
- {
- "@Org.OData.Core.V1.ContentID": "6",
- "CustomerID": "DUMON",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "6.1",
- "OrderID": 10311,
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "unlink",
- "responseCode": 404
- }
- }
- ]
- }
- ]
- }
-Without the continue-on-error
preference processing would stop on the first error, and the response would be a standard OData error response
-HTTP/1.1 400 Bad Request
+HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: ###
-
-{
-"error": {
- "code": "incmplt",
- "message": "Required field(s) not provided",
- "target": "Customers('EASTC')/Address",
- "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
- }
- }
+Preference-Applied: return=minimal, continue-on-error
+
+{
+"@context": "#$delta",
+ "value": [
+ {
+ "@Org.OData.Core.V1.ContentID": "1",
+ "CustomerID": "EASTC",
+ "@removed": {
+ "reason": "changed"
+ },
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "insert",
+ "responseCode": 400,
+ "info": {
+ "code": "incmplt",
+ "message": "Required field(s) not provided",
+ "target": "Address",
+ "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ],
+ "severity": "error"
+ }
+ }
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "2",
+ "CustomerID": "AROUT",
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "update",
+ "responseCode": 400,
+ "info": {
+ "code": "r-o",
+ "message": "Customer is archived and cannot be changed",
+ "severity": "error"
+ }
+ }
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "3",
+ "CustomerID": "ANTON",
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "delete",
+ "responseCode": 400,
+ "info": {
+ "code": "ufo",
+ "message": "Customer has unfinished orders and cannot be deleted",
+ "severity": "error"
+ }
+ }
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4",
+ "CustomerID": "ALFKI",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "4.3",
+ "@id": "Orders(10835)",
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "update",
+ "responseCode": 400,
+ "info": {
+ "code": "b/s",
+ "message": "RequiredDate cannot be changed because Order is already being shipped",
+ "severity": "error"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "5",
+ "CustomerID": "ANATR",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "5.1",
+ "@removed": {
+ "reason": "changed"
+ },
+ "OrderID": 10643,
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "link",
+ "responseCode": 404,
+ "info": null
+ }
+ }
+ ]
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "6",
+ "CustomerID": "DUMON",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "6.1",
+ "OrderID": 10311,
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "unlink",
+ "responseCode": 404
+ }
+ }
+ ]
+ }
+ ]
+ }
+Without the continue-on-error
preference processing would stop on the first error, and the response would be a standard OData error response
+HTTP/1.1 400 Bad Request
+Content-Type: application/json
+Content-Length: ###
+
+{
+"error": {
+ "code": "incmplt",
+ "message": "Required field(s) not provided",
+ "target": "Customers('EASTC')/Address",
+ "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
+ }
+ }
The title
name/value pair contains the function or action title as a string.
If metadata=minimal
is requested, the target
name/value pair MUST be included if its value differs from the canonical function or action URL.
Example 43: minimal representation of a function where all overloads are applicable
-{
-"@context": "http://host/service/$metadata#Employees/$entity",
- "#Model.RemainingVacation": {},
- …
- }
Example 44: full representation of a specific overload with parameter alias for the Year
parameter
Example 44: minimal representation of a function where all overloads are applicable
{
"@context": "http://host/service/$metadata#Employees/$entity",
- "#Model.RemainingVacation(Year)": {
- "title": "Remaining vacation from year.",
- "target": "Employees(2)/RemainingVacation(Year=@Year)"
- },
- …
- }
Example 45: full representation in a collection
+Example 45: full representation of a specific overload with parameter alias for the Year
parameter
{
-"@context": "http://host/service/$metadata#Employees",
- "#Model.RemainingVacation": {
- "title": "Remaining Vacation",
- "target": "Managers(22)/Employees/RemainingVacation"
+ "@context": "http://host/service/$metadata#Employees/$entity",
+ "#Model.RemainingVacation(Year)": {
+ "title": "Remaining vacation from year.",
+ "target": "Employees(2)/RemainingVacation(Year=@Year)"
},
- "value": [ … ]
+ …
}
Example 46: full representation in a nested collection
+Example 46: full representation in a collection
{
-"@context": "http://host/service/$metadata#Employees/$entity",
- "@type": "Model.Manager",
- "ID":22,
- …
- "Employees#RemainingVacation": {
- "title": "RemainingVacation",
- "target": "Managers(22)/Employees/RemainingVacation"
- }
- }
Example 47: full representation in a nested collection
+{
+"@context": "http://host/service/$metadata#Employees/$entity",
+ "@type": "Model.Manager",
+ "ID":22,
+ …
+ "Employees#RemainingVacation": {
+ "title": "RemainingVacation",
+ "target": "Managers(22)/Employees/RemainingVacation"
+ }
+ }
The title
name/value pair contains the function or action title as a string.
If metadata=minimal
is requested, the target
name/value pair MUST be included if its value differs from the canonical function or action URL.
Example 47: minimal representation in an entity
-{
-"@context": "http://host/service/$metadata#LeaveRequests/$entity",
- "#Model.Approve": {},
- …
- }
Example 48: full representation in an entity:
+Example 48: minimal representation in an entity
{
"@context": "http://host/service/$metadata#LeaveRequests/$entity",
- "#Model.Approve": {
- "title": "Approve Leave Request",
- "target": "LeaveRequests(2)/Approve"
- },
- …
- }
Example 49: full representation in a collection
+Example 49: full representation in an entity:
{
-"@context": "http://host/service/$metadata#LeaveRequests",
+ "@context": "http://host/service/$metadata#LeaveRequests/$entity",
"#Model.Approve": {
- "title": "Approve All Leave Requests",
- "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
+ "title": "Approve Leave Request",
+ "target": "LeaveRequests(2)/Approve"
},
- "value": [ … ]
+ …
}
Example 50: full representation in a nested collection
+Example 50: full representation in a collection
{
-"@context": "http://host/service/$metadata#Employees/$entity",
- "@type": "Model.Manager",
- "ID": 22,
- …
- "LeaveRequests#Model.Approve": {
- "title": "Approve All Leave Requests",
- "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
- }
- }
Example 51: full representation in a nested collection
+{
+"@context": "http://host/service/$metadata#Employees/$entity",
+ "@type": "Model.Manager",
+ "ID": 22,
+ …
+ "LeaveRequests#Model.Approve": {
+ "title": "Approve All Leave Requests",
+ "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
+ }
+ }
Each non-binding parameter value is encoded as a separate name/value pair in this JSON object. The name is the name of the parameter. The value is the parameter value in the JSON representation appropriate for its type. Entity typed parameter values MAY include a subset of the properties, or just the entity reference, as appropriate to the action. Stream typed parameter values are represented following the same rules as inlined stream properties.
Entities as parameter values are represented as explained in section 6.
Example 51: Create a quote for a product that does not yet exist. The Product
parameter takes a transient entity.
POST http://host/service/CreateQuote
-Content-Type: application/json
-
-{
-"Product": {
- "Name": "Our best ever",
- "Price": 1
- },
- "CustomerID": "ALFKI"
- }
Example 52: Create a quote for an existing product. The Product
parameter takes a non-transient entity which can be identified through its entity-id:
Example 52: Create a quote for a product that does not yet exist. The Product
parameter takes a transient entity.
POST http://host/service/CreateQuote
Content-Type: application/json
{
"Product": {
- "@id": "Products(14)"
- },
- "CustomerID": "ALFKI"
- }
or, as in section 15.2, through its primary key fields plus, if necessary, its context:
+"Name": "Our best ever", + "Price": 1 + }, + "CustomerID": "ALFKI" + }Example 53: Create a quote for an existing product. The Product
parameter takes a non-transient entity which can be identified through its entity-id:
POST http://host/service/CreateQuote
Content-Type: application/json
{
"Product": {
- "@context": "#Products",
- "ProductID": 14
- },
- "CustomerID": "ALFKI"
- }
or, as in section 15.2, through its primary key fields plus, if necessary, its context:
+POST http://host/service/CreateQuote
+Content-Type: application/json
+
+{
+"Product": {
+ "@context": "#Products",
+ "ProductID": 14
+ },
+ "CustomerID": "ALFKI"
+ }
Alternatively, values of non-binding parameters MAY be specified as common expressions OData-URL, section 5.1.1. In the case of a bound action these MAY contain path expressions OData-URL, section 5.1.1.15, which the service evaluates on the binding parameter value. Such parameters are encoded as name/value pairs where the name is the name of the parameter followed by @expression
and the value is the common expression. As the following example demonstrates, non-transient entities can be passed as non-binding action parameters through a resource path in this way.
Example 53: An employee requests leave from their manager for the next two weeks:
-POST /service/Employees(23)/self.RequestLeave
-Host: host
-Content-Type: application/json
-
-{
-"StartDate@expression": "now()",
- "EndDate@expression": "now() add duration'P14D'",
- "Approver@expression": "Manager"
- }
The expression Manager
is evaluated on the binding parameter value Employees(23)
.
When invoking an unbound action through an action import, expressions involving paths must start with $root
:
POST /service/RequestLeave
+Example 54: An employee requests leave from their manager for the next two weeks:
+POST /service/Employees(23)/self.RequestLeave
Host: host
Content-Type: application/json
{
-"Requester@expression": "$root/services/Employee(23)",
- "StartDate@expression": "now()",
- "EndDate@expression": "now() add duration'P14D'",
- "Approver@expression": "$root/services/Employee(23)/Manager"
- }
+"StartDate@expression": "now()",
+ "EndDate@expression": "now() add duration'P14D'",
+ "Approver@expression": "Manager"
+ }
The expression Manager
is evaluated on the binding parameter value Employees(23)
.
When invoking an unbound action through an action import, expressions involving paths must start with $root
:
POST /service/RequestLeave
+Host: host
+Content-Type: application/json
+
+{
+"Requester@expression": "$root/services/Employee(23)",
+ "StartDate@expression": "now()",
+ "EndDate@expression": "now() add duration'P14D'",
+ "Approver@expression": "$root/services/Employee(23)/Manager"
+ }
Inside a batch request the common expressions can also be value references starting with $
, as introduced in OData-Protocol, section 11.7.6.
Non-binding parameters that are nullable or annotated with the term Core.OptionalParameter
defined in OData-VocCore MAY be omitted from the request body. If an omitted parameter is not annotated (and thus nullable), it MUST be interpreted as having the null
value. If it is annotated and the annotation specifies a DefaultValue
, the omitted parameter is interpreted as having that default value. If omitted and the annotation does not specify a default value, the service is free on how to interpret the omitted parameter. Note: a nullable non-binding parameter is equivalent to being annotated as optional with a default value of null
.
Example 54:
-{
-"param1": 42,
- "param2": {
- "Street": "One Microsoft Way",
- "Zip": 98052
- },
- "param3": [ 1, 42, 99 ],
- "param4": null
- }
Example 55:
+{
+"param1": 42,
+ "param2": {
+ "Street": "One Microsoft Way",
+ "Zip": 98052
+ },
+ "param3": [ 1, 42, 99 ],
+ "param4": null
+ }
In order to invoke an action with no non-binding parameters, the client passes an empty JSON object in the body of the request. 4.01 Services MUST also support clients passing an empty request body for this case.
@@ -2137,7 +2148,7 @@A body
MUST NOT be specified if the method
is get
or delete
.
The request object and the headers
object MUST NOT contain name/value pairs with duplicate names. This is in conformance with RFC7493.
Example 55: a batch request that contains the following individual requests in the order listed
+Example 56: a batch request that contains the following individual requests in the order listed
Note: For brevity, in the example, request bodies are excluded in favor of English descriptions inside <>
brackets and OData-Version
headers are omitted.
POST /service/$batch HTTP/1.1
-Host: host
-OData-Version: 4.01
-Content-Type: application/json
-Content-Length: ###
-
-{
-"requests": [
- {
- "id": "0",
- "method": "get",
- "url": "/service/Customers('ALFKI')"
- },
- {
- "id": "1",
- "atomicityGroup": "group1",
- "dependsOn": [ "0" ],
- "method": "patch",
- "url": "/service/Customers('ALFKI')",
- "headers": {
- "Prefer": "return=minimal"
- },
- "body": <JSON representation of changes to Customer ALFKI>
- },
- {
- "id": "2",
- "atomicityGroup": "group1",
- "method": "post",
- "url": "/service/Customers",
- "body": <JSON representation of a new Customer entity>
- },
- {
- "id": "3",
- "dependsOn": [ "group1" ],
- "method": "get",
- "url": "/service/Products"
- }
- ]
- }
The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location
header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.
Example 56: a batch request that contains the following operations in the order listed:
-id = 1
)id = 1
)POST /service/$batch HTTP/1.1
Host: host
OData-Version: 4.01
@@ -2208,30 +2168,47 @@ {
"requests": [
{
- "id": "1",
- "method": "post",
- "url": "/service/Customers",
- "body": <JSON representation of a new Customer entity>
- },
- {
- "id": "2",
- "dependsOn": [ "1" ]
- "method": "post",
- "url": "$1/Orders",
- "body": <JSON representation of a new Order>
- }
- ]
- }
The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location
header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.
Example 57: a batch request that contains the following operations in the order listed:
id
= 1)id = 1
)id = 1
)POST /service/$batch HTTP/1.1
Host: host
@@ -2243,36 +2220,29 @@ "requests": [
{
"id": "1",
- "method": "get",
- "url": "/service/Employees(0)",
- "headers": {
- "accept": "application/json"
- }
- },
- {
- "id": "2",
- "dependsOn": [ "1" ],
- "method": "patch",
- "url": "/service/Employees(0)",
- "headers": {
- "if-match": "$1"
- },
- "body": {
- "Salary": 75000
- }
- }
- ]
- }
Example 58: a batch request that contains the following operations in the order listed:
Content-ID = 1
)id
= 1)POST /service/$batch HTTP/1.1
Host: host
@@ -2285,7 +2255,7 @@ {
"id": "1",
"method": "get",
- "url": "/service/Employees/0?$select=Building",
+ "url": "/service/Employees(0)",
"headers": {
"accept": "application/json"
}
@@ -2293,14 +2263,55 @@ {
"id": "2",
"dependsOn": [ "1" ],
- "method": "get",
- "url": "/service/Employees?$filter=Building eq $1/Building",
+ "method": "patch",
+ "url": "/service/Employees(0)",
"headers": {
- "accept": "application/json"
- }
- }
- ]
- }
Example 59: a batch request that contains the following operations in the order listed:
+Content-ID = 1
)POST /service/$batch HTTP/1.1
+Host: host
+OData-Version: 4.01
+Content-Type: application/json
+Content-Length: ###
+
+{
+"requests": [
+ {
+ "id": "1",
+ "method": "get",
+ "url": "/service/Employees/0?$select=Building",
+ "headers": {
+ "accept": "application/json"
+ }
+ },
+ {
+ "id": "2",
+ "dependsOn": [ "1" ],
+ "method": "get",
+ "url": "/service/Employees?$filter=Building eq $1/Building",
+ "headers": {
+ "accept": "application/json"
+ }
+ }
+ ]
+ }
If the media type is not exactly equal to application/json
(i.e. it is a subtype or has format parameters), the headers
object MUST contain a name/value pair with the name content-type
whose value is the media type.
Relative URLs in a response object follow the rules for relative URLs based on the request URL of the corresponding request. Especially: URLs in responses MUST NOT contain $
-prefixed request identifiers.
Example 59: referencing the batch request example 55 above, assume all the requests except the final query request succeed. In this case the response would be
-HTTP/1.1 200 OK
-OData-Version: 4.01
-Content-Length: ####
-Content-Type: application/json
-
-{
-"responses": [
- {
- "id": "0",
- "status": 200,
- "body": <JSON representation of the Customer entity with key ALFKI>
- },
- {
- "id": "1",
- "status": 204
- },
- {
- "id": "2",
- "status": 201,
- "headers": {
- "location": "http://host/service.svc/Customer('POIUY')"
- },
- "body": <JSON representation of the new Customer entity>
- },
- {
- "id": "3",
- "status": 404,
- "body": <Error message>
- }
- ]
- }
Example 60: referencing the batch request example 56 above, assume all the requests except the final query request succeed. In this case the response would be
+HTTP/1.1 200 OK
+OData-Version: 4.01
+Content-Length: ####
+Content-Type: application/json
+
+{
+"responses": [
+ {
+ "id": "0",
+ "status": 200,
+ "body": <JSON representation of the Customer entity with key ALFKI>
+ },
+ {
+ "id": "1",
+ "status": 204
+ },
+ {
+ "id": "2",
+ "status": 201,
+ "headers": {
+ "location": "http://host/service.svc/Customer('POIUY')"
+ },
+ "body": <JSON representation of the new Customer entity>
+ },
+ {
+ "id": "3",
+ "status": 404,
+ "body": <Error message>
+ }
+ ]
+ }
respond-async
preference MAY be executed asynchronously. This means that the “outer” batch request is executed asynchronously; this preference does not automatically cascade down to the individual requests within the batch. After successful execution of the batch request the response to the batch request is returned in the body of a response to an interrogation request against the status monitor resource URL, see OData-Protocol, section 11.6.
A service MAY return interim results to an asynchronously executing batch. It does this by responding with 200 OK
to a GET
request to the monitor resource and including a nextLink
control information in the JSON batch response, thus signaling that the response is only a partial result. A subsequent GET
request to the next link MAY result in a 202 Accepted
response with a location
header pointing to a new status monitor resource.
Example 60: referencing the example 55 above again, assume that the request is sent with the respond-async
preference. This results in a 202
response pointing to a status monitor resource:
HTTP/1.1 202 Accepted
-Location: http://service-root/async-monitor-0
-Retry-After: ###
Example 61: referencing the example 56 above again, assume that the request is sent with the respond-async
preference. This results in a 202
response pointing to a status monitor resource:
HTTP/1.1 202 Accepted
+Location: http://service-root/async-monitor-0
+Retry-After: ###
When interrogating the monitor URL only the first request in the batch has finished processing and all the remaining requests are still being processed. The service signals that asynchronous processing is “finished” and returns a partial result with the first response and a next link. The client did not explicitly accept application/http
, so the response is “unwrapped” and only indicates with the AsyncResult
header that it is a response to a status monitor resource:
HTTP/1.1 200 OK
-AsyncResult: 200
-OData-Version: 4.01
-Content-Length: ###
-Content-Type: application/json
-
-{
-"responses": [
- {
- "id": "0",
- "status": 200,
- "body": <JSON representation of the Customer entity with key ALFKI>
- }
- ],
- "@nextLink": "…?$skiptoken=YmF0Y2gx"
- }
HTTP/1.1 200 OK
+AsyncResult: 200
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+"responses": [
+ {
+ "id": "0",
+ "status": 200,
+ "body": <JSON representation of the Customer entity with key ALFKI>
+ }
+ ],
+ "@nextLink": "…?$skiptoken=YmF0Y2gx"
+ }
Client makes a GET
request to the next link and receives a 202
response with the location of a new monitor resource.
HTTP/1.1 202 Accepted
-Location: http://service-root/async-monitor-1
-Retry-After: ###
HTTP/1.1 202 Accepted
+Location: http://service-root/async-monitor-1
+Retry-After: ###
After some time a GET
request to the monitor resource returns the remainder of the result.
HTTP/1.1 200 OK
-AsyncResult: 200
-OData-Version: 4.01
-Content-Length: ###
-Content-Type: application/json
-
-{
-"responses": [
- {
- "id": "1",
- "status": 204
- },
- {
- "id": "2",
- "status": 201,
- "headers": {
- "location": "http://host/service.svc/Customer('POIUY')"
- },
- "body": <JSON representation of the new Customer entity>
- },
- {
- "id": "3",
- "status": 404,
- "body": <Error message>
- }
- ]
- }
HTTP/1.1 200 OK
+AsyncResult: 200
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+"responses": [
+ {
+ "id": "1",
+ "status": 204
+ },
+ {
+ "id": "2",
+ "status": 201,
+ "headers": {
+ "location": "http://host/service.svc/Customer('POIUY')"
+ },
+ "body": <JSON representation of the new Customer entity>
+ },
+ {
+ "id": "3",
+ "status": 404,
+ "body": <Error message>
+ }
+ ]
+ }
In addition to the above interaction pattern individual requests within a batch with no other requests depending on it and not part of an atomicity group MAY be executed asynchronously if they specify the respond-async
preference and if the service responds with a JSON batch response. In this case the response
array contains a response object for each asynchronously executed individual request with a status
of 202
, a location
header pointing to an individual status monitor resource, and optionally a retry-after
header.
Example 61: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously
-HTTP/1.1 200 OK
-OData-Version: 4.01
-Content-Length: ###
-Content-Type: application/json
-
-{
-"responses": [
- {
- "id": "0",
- "status": 202,
- "headers": {
- "location": "http://service-root/async-monitor-0"
- }
- },
- {
- "id": "1",
- "status": 204
- }
- ]
- }
Example 62: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously
+HTTP/1.1 200 OK
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+"responses": [
+ {
+ "id": "0",
+ "status": 202,
+ "headers": {
+ "location": "http://service-root/async-monitor-0"
+ }
+ },
+ {
+ "id": "1",
+ "status": 204
+ }
+ ]
+ }
value
property and are not prefixed with a property name.
Example 62:
-{
-"@context": "http://host/service/$metadata#Customers",
- "@com.example.customer.setkind": "VIPs",
- "value": [
- {
- "@com.example.display.highlight": true,
- "ID": "ALFKI",
- "CompanyName@com.example.display.style": { "title": true, "order": 1 },
- "CompanyName": "Alfreds Futterkiste",
- "Orders@com.example.display.style#simple": { "order": 2 }
- }
- ]
- }
Example 63:
+{
+"@context": "http://host/service/$metadata#Customers",
+ "@com.example.customer.setkind": "VIPs",
+ "value": [
+ {
+ "@com.example.display.highlight": true,
+ "ID": "ALFKI",
+ "CompanyName@com.example.display.style": { "title": true, "order": 1 },
+ "CompanyName": "Alfreds Futterkiste",
+ "Orders@com.example.display.style#simple": { "order": 2 }
+ }
+ ]
+ }
Service implementations SHOULD carefully consider which information to include in production environments to guard against potential security concerns around information disclosure.
Error responses MAY contain annotations in any of its JSON objects.
Example 63:
-{
-"error": {
- "code": "err123",
- "message": "Unsupported functionality",
- "target": "query",
- "details": [
- {
- "code": "forty-two",
- "target": "$search",
- "message": "$search query option not supported"
- }
- ],
- "innererror": {
- "trace": […],
- "context": {…}
- }
- }
- }
Example 64:
+{
+"error": {
+ "code": "err123",
+ "message": "Unsupported functionality",
+ "target": "query",
+ "details": [
+ {
+ "code": "forty-two",
+ "target": "$search",
+ "message": "$search query option not supported"
+ }
+ ],
+ "innererror": {
+ "trace": […],
+ "context": {…}
+ }
+ }
+ }
Control characters (00
to 1F
and 7F
) and Unicode characters beyond 00FF
within JSON strings are encoded as \uXXXX
or \uXXXX\uXXXX
(see RFC8259, section 7)
Example 64: note that this is one HTTP header line without any line breaks or optional whitespace
-OData-error: {"code":"err123","message":"Unsupported
-functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
-query option not supported"}]}
Example 65: note that this is one HTTP header line without any line breaks or optional whitespace
+OData-error: {"code":"err123","message":"Unsupported
+functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
+query option not supported"}]}
Example 31: null
value accompanied by an instance annotation
Example 31: An action is invoked when a utilities customer moves into a building, it returns the address. After a successful move-in it might return the null
value accompanied by an instance annotation:
{
"@context": "http://host/service/$metadata#Model.Address",
"@Core.Messages": [{
- "code": "EPOSTCODE",
- "message": "Could not resolve postcode XYZ",
+ "code": "EADDRESS",
+ "message": "Street name not yet determined",
"severity": "error"
}]
}
An individual property or operation response is represented as a JSON object.
-A single-valued property or operation response that has the null
value and carries no control information or instance annotations does not have a representation; see OData-Protocol.
A single-valued property or operation response that has the null
value does not have a representation provided that it carries no control information other than context
and no instance annotations; see OData-Protocol.
A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is value
and whose value is a primitive value or null
.
A property or operation response that is of complex type is represented as a complex value. If the value is null
, the JSON object consists of name/value pairs for the @context
and the control information and instance annotations only.
A property or operation response that is of complex type is represented as a complex value. If the value is null
, the JSON object consists of name/value pairs for the control information and instance annotations only.
A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is value
. Its value is the JSON representation of a collection of complex type values or collection of primitive values.
Example 26: primitive value
diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index 7deb04a8a..c6fb9ba36 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -1897,10 +1897,10 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value and carries no [control information](#ControlInformation) -or [instance annotations](#InstanceAnnotations) -does not have a representation; see -[OData-Protocol](#ODataProtocol). +`null` value does not have a representation provided that it carries no +[control information](#ControlInformation) other than +[`context`](#ControlInformationcontextodatacontext) +and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is @@ -1909,7 +1909,7 @@ value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented as a [complex value](#ComplexValue). If the value is `null`, the JSON object -consists of name/value pairs for the `@context` and the +consists of name/value pairs for the [control information](#ControlInformation) and [instance annotations](#InstanceAnnotations) only. diff --git a/odata-json-format/10 Media Entity.md b/odata-json-format/10 Media Entity.md index 95ebc2d0d..2c7ddab0e 100644 --- a/odata-json-format/10 Media Entity.md +++ b/odata-json-format/10 Media Entity.md @@ -33,10 +33,10 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value and carries no [control information](#ControlInformation) -or [instance annotations](#InstanceAnnotations) -does not have a representation; see -[OData-Protocol](#ODataProtocol). +`null` value does not have a representation provided that it carries no +[control information](#ControlInformation) other than +[`context`](#ControlInformationcontextodatacontext) +and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is @@ -45,7 +45,7 @@ value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented as a [complex value](#ComplexValue). If the value is `null`, the JSON object -consists of name/value pairs for the `@context` and the +consists of name/value pairs for the [control information](#ControlInformation) and [instance annotations](#InstanceAnnotations) only. From 944edea32653651d96717e1f79b378aabcd8f75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?=An entity is serialized as a JSON object. It MAY contain context
, type
, or deltaLink
control information.
Each property to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant.
+If a nullable single-valued navigation property or entity-valued annotation or return type of an operation has the null
value, the value is serialized as follows:
context
and no instance annotations,
+null
when it occurs in a name/value pair in another JSON object (for example, an expanded single-valued navigation property).Otherwise, each property to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant.
An entity in a payload may be a complete entity, a projected entity (see System Query Option $select
in OData-Protocol), or a partial entity update (see Update an Entity in OData-Protocol).
An entity representation can be (modified and) round-tripped to the service directly. The context URL is used in requests only as a base for relative URLs.
An individual property or operation response is represented as a JSON object.
-A single-valued property or operation response that has the null
value does not have a representation provided that it carries no control information other than context
and no instance annotations; see OData-Protocol.
A single-valued property or operation response that has the null
value does not have a representation provided that, with minimal metadata, it carries no control information other than context
and no instance annotations; see OData-Protocol.
A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is value
and whose value is a primitive value or null
.
A property or operation response that is of complex type is represented as a complex value. If the value is null
, the JSON object consists of name/value pairs for the control information and instance annotations only.
A property or operation response that is of complex type is represented as a complex value. If the value is null
, the context control information is omitted and the JSON object consists of name/value pairs for the other control information and instance annotations only.
A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is value
. Its value is the JSON representation of a collection of complex type values or collection of primitive values.
Note: the context URL is optional in requests.
diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index c6fb9ba36..d1c5cd893 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -1295,7 +1295,21 @@ An entity is serialized as a JSON object. It MAY contain or [`deltaLink`](#ControlInformationdeltaLinkodatadeltaLink) control information. -Each [property](#StructuralProperty) to be transmitted is +If a nullable single-valued navigation property or +entity-valued annotation or return type of an operation has the `null` value, +the value is serialized as follows: +- If, with [minimal metadata](#metadataminimalodatametadataminimal), + the value carries no [control information](#ControlInformation) other than + [`context`](#ControlInformationcontextodatacontext) + and no [instance annotations](#InstanceAnnotations), + - the value does not have a representation as response to a request (see [OData-Protocol, section 9.1.4](https://docs.oasis-open.org/odata/odata/v4.02/odata-v4.02-part1-protocol.html#ResponseCode204NoContent)) + - but is represented by the JSON literal `null` when it occurs in a name/value pair + in another JSON object (for example, an [expanded single-valued navigation property](#ExpandedNavigationProperty)). +- Otherwise the context control information is omitted and the serialization produces + a JSON object consisting of name/value pairs for the + other control information and instance annotations only. + +Otherwise, each [property](#StructuralProperty) to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant. @@ -1897,7 +1911,8 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value does not have a representation provided that it carries no +`null` value does not have a representation provided that, with +[minimal metadata](#metadataminimalodatametadataminimal), it carries no [control information](#ControlInformation) other than [`context`](#ControlInformationcontextodatacontext) and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). @@ -1908,10 +1923,9 @@ represented as an object with a name/value pair whose name is value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented -as a [complex value](#ComplexValue). If the value is `null`, the JSON object -consists of name/value pairs for the -[control information](#ControlInformation) -and [instance annotations](#InstanceAnnotations) only. +as a [complex value](#ComplexValue). If the value is `null`, the context control information +is omitted and the JSON object consists of name/value pairs for the +other control information and instance annotations only. A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is @@ -1979,7 +1993,6 @@ it returns the address. After a successful move-in it might return the `null` value accompanied by an instance annotation: ```json { - "@context": "http://host/service/$metadata#Model.Address", "@Core.Messages": [{ "code": "EADDRESS", "message": "Street name not yet determined", diff --git a/odata-json-format/10 Media Entity.md b/odata-json-format/10 Media Entity.md index 2c7ddab0e..2cea00a2e 100644 --- a/odata-json-format/10 Media Entity.md +++ b/odata-json-format/10 Media Entity.md @@ -33,7 +33,8 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value does not have a representation provided that it carries no +`null` value does not have a representation provided that, with +[minimal metadata](#metadataminimalodatametadataminimal), it carries no [control information](#ControlInformation) other than [`context`](#ControlInformationcontextodatacontext) and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). @@ -44,10 +45,9 @@ represented as an object with a name/value pair whose name is value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented -as a [complex value](#ComplexValue). If the value is `null`, the JSON object -consists of name/value pairs for the -[control information](#ControlInformation) -and [instance annotations](#InstanceAnnotations) only. +as a [complex value](#ComplexValue). If the value is `null`, the context control information +is omitted and the JSON object consists of name/value pairs for the +other control information and instance annotations only. A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is @@ -115,7 +115,6 @@ it returns the address. After a successful move-in it might return the `null` value accompanied by an instance annotation: ```json { - "@context": "http://host/service/$metadata#Model.Address", "@Core.Messages": [{ "code": "EADDRESS", "message": "Street name not yet determined", diff --git a/odata-json-format/5 Service Document.md b/odata-json-format/5 Service Document.md index 6140d0505..baaa719c1 100644 --- a/odata-json-format/5 Service Document.md +++ b/odata-json-format/5 Service Document.md @@ -99,7 +99,21 @@ An entity is serialized as a JSON object. It MAY contain or [`deltaLink`](#ControlInformationdeltaLinkodatadeltaLink) control information. -Each [property](#StructuralProperty) to be transmitted is +If a nullable single-valued navigation property or +entity-valued annotation or return type of an operation has the `null` value, +the value is serialized as follows: +- If, with [minimal metadata](#metadataminimalodatametadataminimal), + the value carries no [control information](#ControlInformation) other than + [`context`](#ControlInformationcontextodatacontext) + and no [instance annotations](#InstanceAnnotations), + - the value does not have a representation as response to a request (see [#OData-Protocol#ResponseCode204NoContent]) + - but is represented by the JSON literal `null` when it occurs in a name/value pair + in another JSON object (for example, an [expanded single-valued navigation property](#ExpandedNavigationProperty)). +- Otherwise the context control information is omitted and the serialization produces + a JSON object consisting of name/value pairs for the + other control information and instance annotations only. + +Otherwise, each [property](#StructuralProperty) to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant. From ebf397218f1a3e4f92d7ec34925da5e8d320f4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?=An entity is serialized as a JSON object. It MAY contain context
, type
, or deltaLink
control information.
If a nullable single-valued navigation property or entity-valued annotation or return type of an operation has the null
value, the value is serialized as follows:
context
and no instance annotations,
-null
when it occurs in a name/value pair in another JSON object (for example, an expanded single-valued navigation property).Otherwise, each property to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant.
+Each property to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant.
An entity in a payload may be a complete entity, a projected entity (see System Query Option $select
in OData-Protocol), or a partial entity update (see Update an Entity in OData-Protocol).
An entity representation can be (modified and) round-tripped to the service directly. The context URL is used in requests only as a base for relative URLs.
An individual property or operation response is represented as a JSON object.
-A single-valued property or operation response that has the null
value does not have a representation provided that, with minimal metadata, it carries no control information other than context
and no instance annotations; see OData-Protocol.
A single-valued property or operation response that has the null
value does not have a representation; see OData-Protocol.
A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is value
and whose value is a primitive value or null
.
A property or operation response that is of complex type is represented as a complex value. If the value is null
, the context control information is omitted and the JSON object consists of name/value pairs for the other control information and instance annotations only.
A property or operation response that is of complex type is represented as a complex value.
A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is value
. Its value is the JSON representation of a collection of complex type values or collection of primitive values.
Example 31: An action is invoked when a utilities customer moves into a building, it returns the address. After a successful move-in it might return the null
value accompanied by an instance annotation:
{
-"@Core.Messages": [{
- "code": "EADDRESS",
- "message": "Street name not yet determined",
- "severity": "error"
- }]
- }
Note: the context URL is optional in requests.
The nextLink
control information MUST be included in a response that represents a partial result.
Example 32:
-{
-"@context": "…",
- "@count": 37,
- "value": [
- { … },
- { … },
- { … }
- ],
- "@nextLink": "…?$skiptoken=342r89"
- }
Example 31:
+{
+"@context": "…",
+ "@count": 37,
+ "value": [
+ { … },
+ { … },
+ { … }
+ ],
+ "@nextLink": "…?$skiptoken=342r89"
+ }
A collection of entity references is represented as a collection of entities, with entity reference representations instead of entity representations as items in the array value of the value
name/value pair.
The outermost JSON object in a response MUST contain a context
control information and MAY contain count
, nextLink
, or deltaLink
control information.
Example 33: entity reference to order 10643
-{
-"@context": "http://host/service/$metadata#$ref",
- "@id": "Orders(10643)"
- }
Example 32: entity reference to order 10643
+{
+"@context": "http://host/service/$metadata#$ref",
+ "@id": "Orders(10643)"
+ }
Example 34: collection of entity references
-{
-"@context": "http://host/service/$metadata#Collection($ref)",
- "value": [
- { "@id": "Orders(10643)" },
- { "@id": "Orders(10759)" }
- ]
- }
Example 33: collection of entity references
+{
+"@context": "http://host/service/$metadata#Collection($ref)",
+ "value": [
+ { "@id": "Orders(10643)" },
+ { "@id": "Orders(10759)" }
+ ]
+ }
If the delta response contains a partial list of changes, it MUST include a next link for the client to retrieve the next set of changes.
The last page of a delta response SHOULD contain a delta link in place of the next link for retrieving subsequent changes once the current set of changes has been applied to the initial set.
Example 35: a 4.01 delta response with three changes, in order of occurrence
+Example 34: a 4.01 delta response with three changes, in order of occurrence
ContactName
for customer BOTTM
was changed to Susan Halvenstern
ANTON
was deletedContactName
for customer ALFKI
was changed to Blake Smithe
{
-"@context": "http://host/service/$metadata#Customers/$delta",
- "@count":3,
- "value": [
- {
- "@id": "Customers('BOTTM')",
- "ContactName": "Susan Halvenstern"
- },
- {
- "@removed": {
- "reason": "deleted"
- },
- "@id": "Customers('ANTON')"
- },
- {
- "@id": "Customers('ALFKI')",
- "ContactName": "Blake Smithe"
- }
- ],
- "@deltaLink": "Customers?$deltatoken=8015"
- }
Example 36: a 4.0 delta response with three changes, in order of occurrence
+{
+"@context": "http://host/service/$metadata#Customers/$delta",
+ "@count":3,
+ "value": [
+ {
+ "@id": "Customers('BOTTM')",
+ "ContactName": "Susan Halvenstern"
+ },
+ {
+ "@removed": {
+ "reason": "deleted"
+ },
+ "@id": "Customers('ANTON')"
+ },
+ {
+ "@id": "Customers('ALFKI')",
+ "ContactName": "Blake Smithe"
+ }
+ ],
+ "@deltaLink": "Customers?$deltatoken=8015"
+ }
Example 35: a 4.0 delta response with three changes, in order of occurrence
ContactName
for customer BOTTM
was changed to Susan Halvenstern
ANTON
was deletedContactName
for customer ALFKI
was changed to Blake Smithe
{
-"@odata.context": "http://host/service/$metadata#Customers/$delta",
- "@odata.count": 3,
- "value": [
- {
- "@odata.id": "Customers('BOTTM')",
- "ContactName": "Susan Halvenstern",
- },
- {
- "@odata.context": "#Customers/$deletedEntity",
- "@odata.id": "Customers('ANTON')"
- },
- {
- "@odata.id": "Customers('ALFKI')",
- "ContactName": "Blake Smithe"
- }
- ],
- "@odata.deltaLink": "Customers?$deltatoken=8015"
- }
{
+"@odata.context": "http://host/service/$metadata#Customers/$delta",
+ "@odata.count": 3,
+ "value": [
+ {
+ "@odata.id": "Customers('BOTTM')",
+ "ContactName": "Susan Halvenstern",
+ },
+ {
+ "@odata.context": "#Customers/$deletedEntity",
+ "@odata.id": "Customers('ANTON')"
+ },
+ {
+ "@odata.id": "Customers('ALFKI')",
+ "ContactName": "Blake Smithe"
+ }
+ ],
+ "@odata.deltaLink": "Customers?$deltatoken=8015"
+ }
reason
— either deleted
, if the entity was deleted (destroyed), or changed
if the entity was removed from membership in the result (i.e., due to a data change).Example 37: deleted entity in OData 4.0 response — note that id
is a property, not control information
{
-"@context": "#Customers/$deletedEntity",
- "reason": "deleted",
- "id": "Customers('ANTON')"
- }
Example 36: deleted entity in OData 4.0 response — note that id
is a property, not control information
{
+"@context": "#Customers/$deletedEntity",
+ "reason": "deleted",
+ "id": "Customers('ANTON')"
+ }
In OData 4.01 payloads the deleted-entity object MUST include the following properties, regardless of the specified metadata
value. For ordered payloads, this control information MUST follow the payload ordering constraints.
For full metadata the context
control information MUST be included. It also MUST be included if the entity set of the deleted entity cannot be determined from the surrounding context.
The deleted-entity object MAY include additional properties of the entity, as well as annotations, and MAY include related entities, related deleted entities, or a delta or full representation of a related collection of entities, to represent related entities that have been modified or deleted.
Example 38: deleted entity in OData 4.01 response with id
control information (prefixed with an @
)
{
-"@context": "#Customers/$deletedEntity",
- "@removed": {
- "reason": "deleted",
- "@myannoation.deletedBy": "Mario"
- },
- "@id": "Customers('ANTON')"
- }
Example 37: deleted entity in OData 4.01 response with id
control information (prefixed with an @
)
{
+"@context": "#Customers/$deletedEntity",
+ "@removed": {
+ "reason": "deleted",
+ "@myannoation.deletedBy": "Mario"
+ },
+ "@id": "Customers('ANTON')"
+ }
Example 39: entity removed OData 4.01 response without id
control information and instead all key fields (ID
is the single key field of Customer
)
{
-"@removed": {},
- "ID": "ANTON"
- }
Example 38: entity removed OData 4.01 response without id
control information and instead all key fields (ID
is the single key field of Customer
)
{
+"@removed": {},
+ "ID": "ANTON"
+ }
If the expanded navigation property represents a delta, it MUST be represented as an array-valued control information delta
on the navigation property. Added/changed entities or entity references are added to the collection. Deleted entities in a nested delta representation represent entities no longer part of the collection. If the deleted entity specifies a reason
as deleted
, then the entity is both removed from the collection and deleted, otherwise it is removed from the collection and only deleted if the navigation property is a containment navigation property. The array MUST NOT contain added or deleted links.
Example 40: changes to related orders represented as a 4.01 nested delta representation
+Example 39: changes to related orders represented as a 4.01 nested delta representation
{
+"@context": "http://host/service/$metadata#Customers/$delta",
+ "@count":3,
+ "value": [
+ {
+ "@id": "Customers('ALFKI')",
+ "Orders@delta": [
+ {
+ "@removed": {
+ "reason": "changed"
+ },
+ "@id": "Orders(10643)"
+ },
+ {
+ "@id": "Orders(10645)",
+ "ShippingAddress": {
+ "Street": "23 Tsawassen Blvd.",
+ "City": "Tsawassen",
+ "Region": "BC",
+ "PostalCode": "T2F 8M4"
+ }
+ }
+ ]
+ },
+ {
+ "@removed": {
+ "reason": "deleted"
+ },
+ "@id": "Customers('ANTON')"
+ },
+ {
+ "@id": "Customers('ALFKI')",
+ "ContactName": "Blake Smithe"
+ }
+ ],
+ "@deltaLink": "Customers?$expand=Orders&$deltatoken=8015"
+ }
If the expanded navigation property is a full representation of the collection, it MUST be represented as an expanded navigation property, and its array value MUST represent the full set of entities related according to that relationship and satisfying any specified expand options, or a partial list containing a nextLink
. Following this chain of next links MUST eventually return the full set of entities related according to that relationship and satisfying any specified expand options; the final page does not include a delta link.
Members of the expanded navigation property MUST be represented as added/changed entities or entity references and MUST NOT include added links, deleted links, or deleted entities. Any entity not represented in the collection has either been removed, deleted, or changed such that it no longer satisfies the expand options in the defining query. In any case, clients SHOULD NOT receive additional notifications for such removed entities.
Example 41: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)
-{
-"@context": "http://host/service/$metadata#Customers/$entity/$delta",
- …
- "Orders@count": 42,
- "Orders": [ … ],
- "Orders@nextLink": "…",
- …
- "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
- }
Example 40: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)
+{
+"@context": "http://host/service/$metadata#Customers/$entity/$delta",
+ …
+ "Orders@count": 42,
+ "Orders": [ … ],
+ "Orders@nextLink": "…",
+ …
+ "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
+ }
context
control information specifies the entity set of the entity. This control information MUST be present for entities are not part of the entity set specified by the context URL, regardless of the specified metadata
value.
Example 42: changes to related orders represented as a 4.0 flattened delta payload
+Example 41: changes to related orders represented as a 4.0 flattened delta payload
ALFKI
ALFKI
{
-"@odata.context": "http://host/service/$metadata#Customers/$delta",
- "@odata.count": 5,
- "value": [
- {
- "@odata.context": "#Customers/$deletedLink",
- "source": "Customers('ALFKI')",
- "relationship": "Orders",
- "target": "Orders(10643)"
- },
- {
- "@odata.context": "#Customers/$link",
- "source": "Customers('BOTTM')",
- "relationship": "Orders",
- "target": "Orders(10645)"
- },
- {
- "@odata.context": "#Orders/$entity",
- "@odata.id": "Orders(10645)",
- "ShippingAddress": {
- "Street": "23 Tsawassen Blvd.",
- "City": "Tsawassen",
- "Region": "BC",
- "PostalCode": "T2F 8M4"
- }
- },
- {
- "@odata.context": "#Customers/$deletedEntity",
- "@odata.id": "Customers('ANTON')"
- },
- {
- "@odata.id": "Customers('ALFKI')",
- "ContactName": "Blake Smithe"
- }
- ],
- "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
- }
{
+"@odata.context": "http://host/service/$metadata#Customers/$delta",
+ "@odata.count": 5,
+ "value": [
+ {
+ "@odata.context": "#Customers/$deletedLink",
+ "source": "Customers('ALFKI')",
+ "relationship": "Orders",
+ "target": "Orders(10643)"
+ },
+ {
+ "@odata.context": "#Customers/$link",
+ "source": "Customers('BOTTM')",
+ "relationship": "Orders",
+ "target": "Orders(10645)"
+ },
+ {
+ "@odata.context": "#Orders/$entity",
+ "@odata.id": "Orders(10645)",
+ "ShippingAddress": {
+ "Street": "23 Tsawassen Blvd.",
+ "City": "Tsawassen",
+ "Region": "BC",
+ "PostalCode": "T2F 8M4"
+ }
+ },
+ {
+ "@odata.context": "#Customers/$deletedEntity",
+ "@odata.id": "Customers('ANTON')"
+ },
+ {
+ "@odata.id": "Customers('ALFKI')",
+ "ContactName": "Blake Smithe"
+ }
+ ],
+ "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
+ }
If a property of an entity is dependent upon the property of another entity within the expanded set of entities being tracked, then both the change to the dependent property as well as the change to the principal property or added/deleted link corresponding to the change to the dependent property are returned in the delta response.
The body of a PATCH
request to a URL identifying a collection of entities is a JSON object. It MUST contain the context
control information with a string value of #$delta
, and it MUST contain an array-valued property named value
containing all added, changed, or deleted entities. OData 4.0 delta payloads MAY additionally include added or deleted links between entities.
Example 43: 4.01 collection-update request for customers with expanded orders represented inline as a delta
+Example 42: 4.01 collection-update request for customers with expanded orders represented inline as a delta
EASTC
ContactName
of customer AROUT
ANATR
DUMON
PATCH /service/Customers HTTP/1.1
-Host: host
-Content-Type: application/json
-Content-Length: ###
-Prefer: return=minimal, continue-on-error
-
-{
-"@context": "#$delta",
- "value": [
- {
- "@Org.OData.Core.V1.ContentID": "1",
- "CustomerID": "EASTC",
- "CompanyName": "Eastern Connection",
- "ContactName": "Ann Devon",
- "ContactTitle": "Sales Agent"
- },
- {
- "@Org.OData.Core.V1.ContentID": "2",
- "CustomerID": "AROUT",
- "ContactName": "Thomas Hardy",
- },
- {
- "@Org.OData.Core.V1.ContentID": "3",
- "@removed": {
- "reason": "deleted"
- },
- "CustomerID": "ANTON"
- },
- {
- "@Org.OData.Core.V1.ContentID": "4",
- "CustomerID": "ALFKI",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "4.1",
- "OrderID": 11011,
- "CustomerID": "ALFKI",
- "EmployeeID": 3,
- "OrderDate": "1998-04-09T00:00:00Z",
- "RequiredDate": "1998-05-07T00:00:00Z",
- "ShippedDate": "1998-04-13T00:00:00Z"
- },
- {
- "@Org.OData.Core.V1.ContentID": "4.2",
- "@id": "Orders(10692)"
- },
- {
- "@Org.OData.Core.V1.ContentID": "4.3",
- "@id": "Orders(10835)",
- "RequiredDate": "1998-01-23T00:00:00Z",
- },
- {
- "@Org.OData.Core.V1.ContentID": "4.4",
- "@removed": {
- "reason": "changed"
- },
- "OrderID": 10643
- }
- ]
- },
- {
- "@Org.OData.Core.V1.ContentID": "5",
- "CustomerID": "ANATR",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "5.1",
- "OrderID": 10643
- }
- ],
- },
- {
- "@Org.OData.Core.V1.ContentID": "6",
- "CustomerID": "DUMON",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "6.1",
- "@removed": {
- "reason": "changed"
- },
- "OrderID": 10311
- }
- ]
- }
- ]
- }
PATCH /service/Customers HTTP/1.1
+Host: host
+Content-Type: application/json
+Content-Length: ###
+Prefer: return=minimal, continue-on-error
+
+{
+"@context": "#$delta",
+ "value": [
+ {
+ "@Org.OData.Core.V1.ContentID": "1",
+ "CustomerID": "EASTC",
+ "CompanyName": "Eastern Connection",
+ "ContactName": "Ann Devon",
+ "ContactTitle": "Sales Agent"
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "2",
+ "CustomerID": "AROUT",
+ "ContactName": "Thomas Hardy",
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "3",
+ "@removed": {
+ "reason": "deleted"
+ },
+ "CustomerID": "ANTON"
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4",
+ "CustomerID": "ALFKI",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "4.1",
+ "OrderID": 11011,
+ "CustomerID": "ALFKI",
+ "EmployeeID": 3,
+ "OrderDate": "1998-04-09T00:00:00Z",
+ "RequiredDate": "1998-05-07T00:00:00Z",
+ "ShippedDate": "1998-04-13T00:00:00Z"
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4.2",
+ "@id": "Orders(10692)"
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4.3",
+ "@id": "Orders(10835)",
+ "RequiredDate": "1998-01-23T00:00:00Z",
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4.4",
+ "@removed": {
+ "reason": "changed"
+ },
+ "OrderID": 10643
+ }
+ ]
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "5",
+ "CustomerID": "ANATR",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "5.1",
+ "OrderID": 10643
+ }
+ ],
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "6",
+ "CustomerID": "DUMON",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "6.1",
+ "@removed": {
+ "reason": "changed"
+ },
+ "OrderID": 10311
+ }
+ ]
+ }
+ ]
+ }
Assuming all changes can be applied without errors, the response would be
HTTP/1.1 204 No Content
Preference-Applied: return=minimal, continue-on-error
@@ -1805,124 +1786,124 @@ Add order 10643 to customer ‘ANATR’ - failed without further info
Remove order 10311 from customer ‘DUMON’ - failed without further info
-HTTP/1.1 200 OK
+HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: ###
+Preference-Applied: return=minimal, continue-on-error
+
+{
+"@context": "#$delta",
+ "value": [
+ {
+ "@Org.OData.Core.V1.ContentID": "1",
+ "CustomerID": "EASTC",
+ "@removed": {
+ "reason": "changed"
+ },
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "insert",
+ "responseCode": 400,
+ "info": {
+ "code": "incmplt",
+ "message": "Required field(s) not provided",
+ "target": "Address",
+ "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ],
+ "severity": "error"
+ }
+ }
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "2",
+ "CustomerID": "AROUT",
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "update",
+ "responseCode": 400,
+ "info": {
+ "code": "r-o",
+ "message": "Customer is archived and cannot be changed",
+ "severity": "error"
+ }
+ }
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "3",
+ "CustomerID": "ANTON",
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "delete",
+ "responseCode": 400,
+ "info": {
+ "code": "ufo",
+ "message": "Customer has unfinished orders and cannot be deleted",
+ "severity": "error"
+ }
+ }
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "4",
+ "CustomerID": "ALFKI",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "4.3",
+ "@id": "Orders(10835)",
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "update",
+ "responseCode": 400,
+ "info": {
+ "code": "b/s",
+ "message": "RequiredDate cannot be changed because Order is already being shipped",
+ "severity": "error"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "5",
+ "CustomerID": "ANATR",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "5.1",
+ "@removed": {
+ "reason": "changed"
+ },
+ "OrderID": 10643,
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "link",
+ "responseCode": 404,
+ "info": null
+ }
+ }
+ ]
+ },
+ {
+ "@Org.OData.Core.V1.ContentID": "6",
+ "CustomerID": "DUMON",
+ "Orders@delta": [
+ {
+ "@Org.OData.Core.V1.ContentID": "6.1",
+ "OrderID": 10311,
+ "@Org.OData.Core.V1.DataModificationException": {
+ "failedOperation": "unlink",
+ "responseCode": 404
+ }
+ }
+ ]
+ }
+ ]
+ }
+Without the continue-on-error
preference processing would stop on the first error, and the response would be a standard OData error response
+HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: ###
-Preference-Applied: return=minimal, continue-on-error
-
-{
-"@context": "#$delta",
- "value": [
- {
- "@Org.OData.Core.V1.ContentID": "1",
- "CustomerID": "EASTC",
- "@removed": {
- "reason": "changed"
- },
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "insert",
- "responseCode": 400,
- "info": {
- "code": "incmplt",
- "message": "Required field(s) not provided",
- "target": "Address",
- "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ],
- "severity": "error"
- }
- }
- },
- {
- "@Org.OData.Core.V1.ContentID": "2",
- "CustomerID": "AROUT",
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "update",
- "responseCode": 400,
- "info": {
- "code": "r-o",
- "message": "Customer is archived and cannot be changed",
- "severity": "error"
- }
- }
- },
- {
- "@Org.OData.Core.V1.ContentID": "3",
- "CustomerID": "ANTON",
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "delete",
- "responseCode": 400,
- "info": {
- "code": "ufo",
- "message": "Customer has unfinished orders and cannot be deleted",
- "severity": "error"
- }
- }
- },
- {
- "@Org.OData.Core.V1.ContentID": "4",
- "CustomerID": "ALFKI",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "4.3",
- "@id": "Orders(10835)",
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "update",
- "responseCode": 400,
- "info": {
- "code": "b/s",
- "message": "RequiredDate cannot be changed because Order is already being shipped",
- "severity": "error"
- }
- }
- }
- ]
- },
- {
- "@Org.OData.Core.V1.ContentID": "5",
- "CustomerID": "ANATR",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "5.1",
- "@removed": {
- "reason": "changed"
- },
- "OrderID": 10643,
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "link",
- "responseCode": 404,
- "info": null
- }
- }
- ]
- },
- {
- "@Org.OData.Core.V1.ContentID": "6",
- "CustomerID": "DUMON",
- "Orders@delta": [
- {
- "@Org.OData.Core.V1.ContentID": "6.1",
- "OrderID": 10311,
- "@Org.OData.Core.V1.DataModificationException": {
- "failedOperation": "unlink",
- "responseCode": 404
- }
- }
- ]
- }
- ]
- }
-Without the continue-on-error
preference processing would stop on the first error, and the response would be a standard OData error response
-HTTP/1.1 400 Bad Request
-Content-Type: application/json
-Content-Length: ###
-
-{
-"error": {
- "code": "incmplt",
- "message": "Required field(s) not provided",
- "target": "Customers('EASTC')/Address",
- "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
- }
- }
+
+{
+"error": {
+ "code": "incmplt",
+ "message": "Required field(s) not provided",
+ "target": "Customers('EASTC')/Address",
+ "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
+ }
+ }
The title
name/value pair contains the function or action title as a string.
If metadata=minimal
is requested, the target
name/value pair MUST be included if its value differs from the canonical function or action URL.
Example 44: minimal representation of a function where all overloads are applicable
+Example 43: minimal representation of a function where all overloads are applicable
+{
+"@context": "http://host/service/$metadata#Employees/$entity",
+ "#Model.RemainingVacation": {},
+ …
+ }
Example 44: full representation of a specific overload with parameter alias for the Year
parameter
{
"@context": "http://host/service/$metadata#Employees/$entity",
- "#Model.RemainingVacation": {},
- …
- }
Example 45: full representation of a specific overload with parameter alias for the Year
parameter
Example 45: full representation in a collection
{
-"@context": "http://host/service/$metadata#Employees/$entity",
- "#Model.RemainingVacation(Year)": {
- "title": "Remaining vacation from year.",
- "target": "Employees(2)/RemainingVacation(Year=@Year)"
+ "@context": "http://host/service/$metadata#Employees",
+ "#Model.RemainingVacation": {
+ "title": "Remaining Vacation",
+ "target": "Managers(22)/Employees/RemainingVacation"
},
- …
+ "value": [ … ]
}
Example 46: full representation in a collection
+Example 46: full representation in a nested collection
{
-"@context": "http://host/service/$metadata#Employees",
- "#Model.RemainingVacation": {
- "title": "Remaining Vacation",
- "target": "Managers(22)/Employees/RemainingVacation"
- },
- "value": [ … ]
- }
Example 47: full representation in a nested collection
-{
-"@context": "http://host/service/$metadata#Employees/$entity",
- "@type": "Model.Manager",
- "ID":22,
- …
- "Employees#RemainingVacation": {
- "title": "RemainingVacation",
- "target": "Managers(22)/Employees/RemainingVacation"
- }
- }
The title
name/value pair contains the function or action title as a string.
If metadata=minimal
is requested, the target
name/value pair MUST be included if its value differs from the canonical function or action URL.
Example 48: minimal representation in an entity
+Example 47: minimal representation in an entity
+{
+"@context": "http://host/service/$metadata#LeaveRequests/$entity",
+ "#Model.Approve": {},
+ …
+ }
Example 48: full representation in an entity:
{
"@context": "http://host/service/$metadata#LeaveRequests/$entity",
- "#Model.Approve": {},
- …
- }
Example 49: full representation in an entity:
+Example 49: full representation in a collection
{
-"@context": "http://host/service/$metadata#LeaveRequests/$entity",
+ "@context": "http://host/service/$metadata#LeaveRequests",
"#Model.Approve": {
- "title": "Approve Leave Request",
- "target": "LeaveRequests(2)/Approve"
+ "title": "Approve All Leave Requests",
+ "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
},
- …
+ "value": [ … ]
}
Example 50: full representation in a collection
+Example 50: full representation in a nested collection
{
-"@context": "http://host/service/$metadata#LeaveRequests",
- "#Model.Approve": {
- "title": "Approve All Leave Requests",
- "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
- },
- "value": [ … ]
- }
Example 51: full representation in a nested collection
-{
-"@context": "http://host/service/$metadata#Employees/$entity",
- "@type": "Model.Manager",
- "ID": 22,
- …
- "LeaveRequests#Model.Approve": {
- "title": "Approve All Leave Requests",
- "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
- }
- }
Each non-binding parameter value is encoded as a separate name/value pair in this JSON object. The name is the name of the parameter. The value is the parameter value in the JSON representation appropriate for its type. Entity typed parameter values MAY include a subset of the properties, or just the entity reference, as appropriate to the action. Stream typed parameter values are represented following the same rules as inlined stream properties.
Entities as parameter values are represented as explained in section 6.
Example 52: Create a quote for a product that does not yet exist. The Product
parameter takes a transient entity.
Example 51: Create a quote for a product that does not yet exist. The Product
parameter takes a transient entity.
POST http://host/service/CreateQuote
+Content-Type: application/json
+
+{
+"Product": {
+ "Name": "Our best ever",
+ "Price": 1
+ },
+ "CustomerID": "ALFKI"
+ }
Example 52: Create a quote for an existing product. The Product
parameter takes a non-transient entity which can be identified through its entity-id:
POST http://host/service/CreateQuote
Content-Type: application/json
{
"Product": {
- "Name": "Our best ever",
- "Price": 1
- },
- "CustomerID": "ALFKI"
- }
Example 53: Create a quote for an existing product. The Product
parameter takes a non-transient entity which can be identified through its entity-id:
or, as in section 15.2, through its primary key fields plus, if necessary, its context:
POST http://host/service/CreateQuote
Content-Type: application/json
{
"Product": {
- "@id": "Products(14)"
- },
- "CustomerID": "ALFKI"
- }
or, as in section 15.2, through its primary key fields plus, if necessary, its context:
-POST http://host/service/CreateQuote
-Content-Type: application/json
-
-{
-"Product": {
- "@context": "#Products",
- "ProductID": 14
- },
- "CustomerID": "ALFKI"
- }
Alternatively, values of non-binding parameters MAY be specified as common expressions OData-URL, section 5.1.1. In the case of a bound action these MAY contain path expressions OData-URL, section 5.1.1.15, which the service evaluates on the binding parameter value. Such parameters are encoded as name/value pairs where the name is the name of the parameter followed by @expression
and the value is the common expression. As the following example demonstrates, non-transient entities can be passed as non-binding action parameters through a resource path in this way.
Example 54: An employee requests leave from their manager for the next two weeks:
-POST /service/Employees(23)/self.RequestLeave
+Example 53: An employee requests leave from their manager for the next two weeks:
+POST /service/Employees(23)/self.RequestLeave
+Host: host
+Content-Type: application/json
+
+{
+"StartDate@expression": "now()",
+ "EndDate@expression": "now() add duration'P14D'",
+ "Approver@expression": "Manager"
+ }
+The expression Manager
is evaluated on the binding parameter value Employees(23)
.
+When invoking an unbound action through an action import, expressions involving paths must start with $root
:
+POST /service/RequestLeave
Host: host
Content-Type: application/json
{
-"StartDate@expression": "now()",
- "EndDate@expression": "now() add duration'P14D'",
- "Approver@expression": "Manager"
- }
-The expression Manager
is evaluated on the binding parameter value Employees(23)
.
-When invoking an unbound action through an action import, expressions involving paths must start with $root
:
-POST /service/RequestLeave
-Host: host
-Content-Type: application/json
-
-{
-"Requester@expression": "$root/services/Employee(23)",
- "StartDate@expression": "now()",
- "EndDate@expression": "now() add duration'P14D'",
- "Approver@expression": "$root/services/Employee(23)/Manager"
- }
+"Requester@expression": "$root/services/Employee(23)",
+ "StartDate@expression": "now()",
+ "EndDate@expression": "now() add duration'P14D'",
+ "Approver@expression": "$root/services/Employee(23)/Manager"
+ }
Inside a batch request the common expressions can also be value references starting with $
, as introduced in OData-Protocol, section 11.7.6.
Non-binding parameters that are nullable or annotated with the term Core.OptionalParameter
defined in OData-VocCore MAY be omitted from the request body. If an omitted parameter is not annotated (and thus nullable), it MUST be interpreted as having the null
value. If it is annotated and the annotation specifies a DefaultValue
, the omitted parameter is interpreted as having that default value. If omitted and the annotation does not specify a default value, the service is free on how to interpret the omitted parameter. Note: a nullable non-binding parameter is equivalent to being annotated as optional with a default value of null
.
Example 55:
-{
-"param1": 42,
- "param2": {
- "Street": "One Microsoft Way",
- "Zip": 98052
- },
- "param3": [ 1, 42, 99 ],
- "param4": null
- }
Example 54:
+{
+"param1": 42,
+ "param2": {
+ "Street": "One Microsoft Way",
+ "Zip": 98052
+ },
+ "param3": [ 1, 42, 99 ],
+ "param4": null
+ }
In order to invoke an action with no non-binding parameters, the client passes an empty JSON object in the body of the request. 4.01 Services MUST also support clients passing an empty request body for this case.
@@ -2156,7 +2137,7 @@A body
MUST NOT be specified if the method
is get
or delete
.
The request object and the headers
object MUST NOT contain name/value pairs with duplicate names. This is in conformance with RFC7493.
Example 56: a batch request that contains the following individual requests in the order listed
+Example 55: a batch request that contains the following individual requests in the order listed
Note: For brevity, in the example, request bodies are excluded in favor of English descriptions inside <>
brackets and OData-Version
headers are omitted.
POST /service/$batch HTTP/1.1
+Host: host
+OData-Version: 4.01
+Content-Type: application/json
+Content-Length: ###
+
+{
+"requests": [
+ {
+ "id": "0",
+ "method": "get",
+ "url": "/service/Customers('ALFKI')"
+ },
+ {
+ "id": "1",
+ "atomicityGroup": "group1",
+ "dependsOn": [ "0" ],
+ "method": "patch",
+ "url": "/service/Customers('ALFKI')",
+ "headers": {
+ "Prefer": "return=minimal"
+ },
+ "body": <JSON representation of changes to Customer ALFKI>
+ },
+ {
+ "id": "2",
+ "atomicityGroup": "group1",
+ "method": "post",
+ "url": "/service/Customers",
+ "body": <JSON representation of a new Customer entity>
+ },
+ {
+ "id": "3",
+ "dependsOn": [ "group1" ],
+ "method": "get",
+ "url": "/service/Products"
+ }
+ ]
+ }
The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location
header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.
Example 56: a batch request that contains the following operations in the order listed:
+id = 1
)id = 1
)POST /service/$batch HTTP/1.1
Host: host
OData-Version: 4.01
@@ -2176,47 +2208,30 @@ 19.1 Batch
{
"requests": [
{
- "id": "0",
- "method": "get",
- "url": "/service/Customers('ALFKI')"
- },
- {
- "id": "1",
- "atomicityGroup": "group1",
- "dependsOn": [ "0" ],
- "method": "patch",
- "url": "/service/Customers('ALFKI')",
- "headers": {
- "Prefer": "return=minimal"
- },
- "body": <JSON representation of changes to Customer ALFKI>
- },
- {
- "id": "2",
- "atomicityGroup": "group1",
- "method": "post",
- "url": "/service/Customers",
- "body": <JSON representation of a new Customer entity>
- },
- {
- "id": "3",
- "dependsOn": [ "group1" ],
- "method": "get",
- "url": "/service/Products"
- }
- ]
- }
The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location
header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.
Example 57: a batch request that contains the following operations in the order listed:
id = 1
)id = 1
)id
= 1)POST /service/$batch HTTP/1.1
Host: host
@@ -2228,29 +2243,36 @@ "requests": [
{
"id": "1",
- "method": "post",
- "url": "/service/Customers",
- "body": <JSON representation of a new Customer entity>
- },
- {
- "id": "2",
- "dependsOn": [ "1" ]
- "method": "post",
- "url": "$1/Orders",
- "body": <JSON representation of a new Order>
- }
- ]
- }
Example 58: a batch request that contains the following operations in the order listed:
id
= 1)Content-ID = 1
)POST /service/$batch HTTP/1.1
Host: host
@@ -2263,7 +2285,7 @@ {
"id": "1",
"method": "get",
- "url": "/service/Employees(0)",
+ "url": "/service/Employees/0?$select=Building",
"headers": {
"accept": "application/json"
}
@@ -2271,55 +2293,14 @@ {
"id": "2",
"dependsOn": [ "1" ],
- "method": "patch",
- "url": "/service/Employees(0)",
+ "method": "get",
+ "url": "/service/Employees?$filter=Building eq $1/Building",
"headers": {
- "if-match": "$1"
- },
- "body": {
- "Salary": 75000
- }
- }
- ]
- }
Example 59: a batch request that contains the following operations in the order listed:
-Content-ID = 1
)POST /service/$batch HTTP/1.1
-Host: host
-OData-Version: 4.01
-Content-Type: application/json
-Content-Length: ###
-
-{
-"requests": [
- {
- "id": "1",
- "method": "get",
- "url": "/service/Employees/0?$select=Building",
- "headers": {
- "accept": "application/json"
- }
- },
- {
- "id": "2",
- "dependsOn": [ "1" ],
- "method": "get",
- "url": "/service/Employees?$filter=Building eq $1/Building",
- "headers": {
- "accept": "application/json"
- }
- }
- ]
- }
If the media type is not exactly equal to application/json
(i.e. it is a subtype or has format parameters), the headers
object MUST contain a name/value pair with the name content-type
whose value is the media type.
Relative URLs in a response object follow the rules for relative URLs based on the request URL of the corresponding request. Especially: URLs in responses MUST NOT contain $
-prefixed request identifiers.
Example 60: referencing the batch request example 56 above, assume all the requests except the final query request succeed. In this case the response would be
-HTTP/1.1 200 OK
-OData-Version: 4.01
-Content-Length: ####
-Content-Type: application/json
-
-{
-"responses": [
- {
- "id": "0",
- "status": 200,
- "body": <JSON representation of the Customer entity with key ALFKI>
- },
- {
- "id": "1",
- "status": 204
- },
- {
- "id": "2",
- "status": 201,
- "headers": {
- "location": "http://host/service.svc/Customer('POIUY')"
- },
- "body": <JSON representation of the new Customer entity>
- },
- {
- "id": "3",
- "status": 404,
- "body": <Error message>
- }
- ]
- }
Example 59: referencing the batch request example 55 above, assume all the requests except the final query request succeed. In this case the response would be
+HTTP/1.1 200 OK
+OData-Version: 4.01
+Content-Length: ####
+Content-Type: application/json
+
+{
+"responses": [
+ {
+ "id": "0",
+ "status": 200,
+ "body": <JSON representation of the Customer entity with key ALFKI>
+ },
+ {
+ "id": "1",
+ "status": 204
+ },
+ {
+ "id": "2",
+ "status": 201,
+ "headers": {
+ "location": "http://host/service.svc/Customer('POIUY')"
+ },
+ "body": <JSON representation of the new Customer entity>
+ },
+ {
+ "id": "3",
+ "status": 404,
+ "body": <Error message>
+ }
+ ]
+ }
respond-async
preference MAY be executed asynchronously. This means that the “outer” batch request is executed asynchronously; this preference does not automatically cascade down to the individual requests within the batch. After successful execution of the batch request the response to the batch request is returned in the body of a response to an interrogation request against the status monitor resource URL, see OData-Protocol, section 11.6.
A service MAY return interim results to an asynchronously executing batch. It does this by responding with 200 OK
to a GET
request to the monitor resource and including a nextLink
control information in the JSON batch response, thus signaling that the response is only a partial result. A subsequent GET
request to the next link MAY result in a 202 Accepted
response with a location
header pointing to a new status monitor resource.
Example 61: referencing the example 56 above again, assume that the request is sent with the respond-async
preference. This results in a 202
response pointing to a status monitor resource:
HTTP/1.1 202 Accepted
-Location: http://service-root/async-monitor-0
-Retry-After: ###
Example 60: referencing the example 55 above again, assume that the request is sent with the respond-async
preference. This results in a 202
response pointing to a status monitor resource:
HTTP/1.1 202 Accepted
+Location: http://service-root/async-monitor-0
+Retry-After: ###
When interrogating the monitor URL only the first request in the batch has finished processing and all the remaining requests are still being processed. The service signals that asynchronous processing is “finished” and returns a partial result with the first response and a next link. The client did not explicitly accept application/http
, so the response is “unwrapped” and only indicates with the AsyncResult
header that it is a response to a status monitor resource:
HTTP/1.1 200 OK
-AsyncResult: 200
-OData-Version: 4.01
-Content-Length: ###
-Content-Type: application/json
-
-{
-"responses": [
- {
- "id": "0",
- "status": 200,
- "body": <JSON representation of the Customer entity with key ALFKI>
- }
- ],
- "@nextLink": "…?$skiptoken=YmF0Y2gx"
- }
HTTP/1.1 200 OK
+AsyncResult: 200
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+"responses": [
+ {
+ "id": "0",
+ "status": 200,
+ "body": <JSON representation of the Customer entity with key ALFKI>
+ }
+ ],
+ "@nextLink": "…?$skiptoken=YmF0Y2gx"
+ }
Client makes a GET
request to the next link and receives a 202
response with the location of a new monitor resource.
HTTP/1.1 202 Accepted
-Location: http://service-root/async-monitor-1
-Retry-After: ###
HTTP/1.1 202 Accepted
+Location: http://service-root/async-monitor-1
+Retry-After: ###
After some time a GET
request to the monitor resource returns the remainder of the result.
HTTP/1.1 200 OK
-AsyncResult: 200
-OData-Version: 4.01
-Content-Length: ###
-Content-Type: application/json
-
-{
-"responses": [
- {
- "id": "1",
- "status": 204
- },
- {
- "id": "2",
- "status": 201,
- "headers": {
- "location": "http://host/service.svc/Customer('POIUY')"
- },
- "body": <JSON representation of the new Customer entity>
- },
- {
- "id": "3",
- "status": 404,
- "body": <Error message>
- }
- ]
- }
HTTP/1.1 200 OK
+AsyncResult: 200
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+"responses": [
+ {
+ "id": "1",
+ "status": 204
+ },
+ {
+ "id": "2",
+ "status": 201,
+ "headers": {
+ "location": "http://host/service.svc/Customer('POIUY')"
+ },
+ "body": <JSON representation of the new Customer entity>
+ },
+ {
+ "id": "3",
+ "status": 404,
+ "body": <Error message>
+ }
+ ]
+ }
In addition to the above interaction pattern individual requests within a batch with no other requests depending on it and not part of an atomicity group MAY be executed asynchronously if they specify the respond-async
preference and if the service responds with a JSON batch response. In this case the response
array contains a response object for each asynchronously executed individual request with a status
of 202
, a location
header pointing to an individual status monitor resource, and optionally a retry-after
header.
Example 62: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously
-HTTP/1.1 200 OK
-OData-Version: 4.01
-Content-Length: ###
-Content-Type: application/json
-
-{
-"responses": [
- {
- "id": "0",
- "status": 202,
- "headers": {
- "location": "http://service-root/async-monitor-0"
- }
- },
- {
- "id": "1",
- "status": 204
- }
- ]
- }
Example 61: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously
+HTTP/1.1 200 OK
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+"responses": [
+ {
+ "id": "0",
+ "status": 202,
+ "headers": {
+ "location": "http://service-root/async-monitor-0"
+ }
+ },
+ {
+ "id": "1",
+ "status": 204
+ }
+ ]
+ }
value
property and are not prefixed with a property name.
Example 63:
-{
-"@context": "http://host/service/$metadata#Customers",
- "@com.example.customer.setkind": "VIPs",
- "value": [
- {
- "@com.example.display.highlight": true,
- "ID": "ALFKI",
- "CompanyName@com.example.display.style": { "title": true, "order": 1 },
- "CompanyName": "Alfreds Futterkiste",
- "Orders@com.example.display.style#simple": { "order": 2 }
- }
- ]
- }
Example 62:
+{
+"@context": "http://host/service/$metadata#Customers",
+ "@com.example.customer.setkind": "VIPs",
+ "value": [
+ {
+ "@com.example.display.highlight": true,
+ "ID": "ALFKI",
+ "CompanyName@com.example.display.style": { "title": true, "order": 1 },
+ "CompanyName": "Alfreds Futterkiste",
+ "Orders@com.example.display.style#simple": { "order": 2 }
+ }
+ ]
+ }
Service implementations SHOULD carefully consider which information to include in production environments to guard against potential security concerns around information disclosure.
Error responses MAY contain annotations in any of its JSON objects.
Example 64:
-{
-"error": {
- "code": "err123",
- "message": "Unsupported functionality",
- "target": "query",
- "details": [
- {
- "code": "forty-two",
- "target": "$search",
- "message": "$search query option not supported"
- }
- ],
- "innererror": {
- "trace": […],
- "context": {…}
- }
- }
- }
Example 63:
+{
+"error": {
+ "code": "err123",
+ "message": "Unsupported functionality",
+ "target": "query",
+ "details": [
+ {
+ "code": "forty-two",
+ "target": "$search",
+ "message": "$search query option not supported"
+ }
+ ],
+ "innererror": {
+ "trace": […],
+ "context": {…}
+ }
+ }
+ }
Control characters (00
to 1F
and 7F
) and Unicode characters beyond 00FF
within JSON strings are encoded as \uXXXX
or \uXXXX\uXXXX
(see RFC8259, section 7)
Example 65: note that this is one HTTP header line without any line breaks or optional whitespace
-OData-error: {"code":"err123","message":"Unsupported
-functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
-query option not supported"}]}
Example 64: note that this is one HTTP header line without any line breaks or optional whitespace
+OData-error: {"code":"err123","message":"Unsupported
+functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
+query option not supported"}]}
204 No Content
A request returns 204 No Content
if the requested resource has the null
value, or if the service applies a return=minimal
preference. In this case, the response body MUST be empty.
A request returns 204 No Content
if the requested resource has the null
value and carries no control information OData-JSON, section 4.6 other than what the minimal metadata format OData-JSON, section 3.1.1 requires and no instance annotations.
It also returns 204 No Content
if the service applies a return=minimal
preference.
In these cases, the response body MUST be empty.
+If the requested resource has the null
value but carries additional control information or instance annotations, the request returns 200 OK
instead but omits the context URL from the representation of the response, which then consists of the other control information and instance annotations only.
As defined in RFC9110, a Data Modification Request that responds with 204 No Content
MAY include an ETag
header with a value reflecting the result of the data modification if and only if the client can reasonably “know” the new representation of the resource without actually receiving it. For a PUT
request this means that the response body of a corresponding 200 OK
or 201 Created
response would have been identical to the request body, i.e. no server-side modification of values sent in the request body, no server-calculated values etc. For a PATCH
request this means that the response body of a corresponding 200 OK
or 201 Created
response would have consisted of all values sent in the request body, plus (for values not sent in the request body) server-side values corresponding to the ETag
value sent in the If-Match
header of the PATCH
request, i.e. the previous values “known” to the client.
204 No Content
A request returns 204 No Content
if the requested resource has the null
value and carries no control information OData-JSON, section 4.6 other than what the minimal metadata format OData-JSON, section 3.1.1 requires and no instance annotations.
It also returns 204 No Content
if the service applies a return=minimal
preference.
In these cases, the response body MUST be empty.
+A request returns 204 No Content
if the requested resource has the null
value and carries no control information OData-JSON, section 4.6 other than what the minimal metadata format OData-JSON, section 3.1.1 demands and no instance annotations.
If the requested resource has the null
value but carries additional control information or instance annotations, the request returns 200 OK
instead but omits the context URL from the representation of the response, which then consists of the other control information and instance annotations only.
A request always returns 204 No Content
if the service applies a return=minimal
preference.
With response code 204
, the response body MUST be empty.
As defined in RFC9110, a Data Modification Request that responds with 204 No Content
MAY include an ETag
header with a value reflecting the result of the data modification if and only if the client can reasonably “know” the new representation of the resource without actually receiving it. For a PUT
request this means that the response body of a corresponding 200 OK
or 201 Created
response would have been identical to the request body, i.e. no server-side modification of values sent in the request body, no server-calculated values etc. For a PATCH
request this means that the response body of a corresponding 200 OK
or 201 Created
response would have consisted of all values sent in the request body, plus (for values not sent in the request body) server-side values corresponding to the ETag
value sent in the If-Match
header of the PATCH
request, i.e. the previous values “known” to the client.