You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ko...@apache.org on 2015/02/23 11:11:13 UTC

[06/41] olingo-odata4-js git commit: [OLINGO-541] Move the odatajs branch one directory up

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/503b4417/tests/odata-json-light-tests.js
----------------------------------------------------------------------
diff --git a/tests/odata-json-light-tests.js b/tests/odata-json-light-tests.js
new file mode 100644
index 0000000..fd2c8d4
--- /dev/null
+++ b/tests/odata-json-light-tests.js
@@ -0,0 +1,2492 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// odata-json-light-tests.js
+
+(function (window, undefined) {
+
+    // DATAJS INTERNAL START
+
+    var mockHttpClient;
+
+    module("Unit", {
+        setup: function () {
+            mockHttpClient = window.MockHttpClient.clear();
+        }
+    });
+
+    var getSampleModel = function () {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "NS",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "key": { "propertyRef": [{ "name": "Id"}] },
+                        "property": [
+                                { "name": "Id", "type": "Edm.String" },
+                                { "name": "P1", "type": "Edm.Int32" }
+                         ]
+                    }],
+                    entityContainer: [{
+                        name: "TestContainer",
+                        isDefaultEntityContainer: "true",
+                        entitySet: [{ "name": "EntityTypes", "entityType": "NS.EntityType"}]
+                    }]
+                }]
+            }
+        };
+        return testModel;
+    };
+
+    var getSampleModelWithTwoKeys = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].key = { "propertyRef": [{ "name": "Id" }, { "name": "P1"}] };
+        return testModel;
+    };
+
+    var getSampleModelWithOneConcurrencyProperty = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[0].concurrencyMode = "Fixed";
+        return testModel;
+    };
+    
+    var getSampleModelWithOneBinaryConcurrencyProperty = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[1].concurrencyMode = "Fixed";
+        testModel.dataServices.schema[0].entityType[0].property[1].type = "Edm.Binary";
+        return testModel;
+    };
+
+    var getSampleModelWithMultipleConcurrencyProperties = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[0].concurrencyMode = "Fixed";
+        testModel.dataServices.schema[0].entityType[0].property[1].concurrencyMode = "Fixed";
+        return testModel;
+    };
+
+    var getSampleModelWithDateTimeConcurrencyProperties = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[1] = { "name": "P1", "type": "Edm.DateTime", concurrencyMode: "Fixed" };
+        return testModel;
+    };
+    
+    var getSampleModelWithDecimalProperty = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[1] = { "name": "P1", "type": "Edm.Decimal"};
+        return testModel;
+    };
+
+    var getSampleModelWithNavPropertiesAndInheritedTypes = function () {
+        return {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "maxDataServiceVersion": "4.0",
+                "schema": [
+                    {
+                        "namespace": "ODataDemo",
+                        "entityType": [
+                            {
+                                "name": "Product",
+                                "key": {
+                                    "propertyRef": [
+                                        {
+                                            "name": "ID"
+                                        }
+                                    ]
+                                },
+                                "property": [
+                                    {
+                                        "name": "ID",
+                                        "nullable": "false",
+                                        "type": "Edm.Int32"
+                                    }
+                                ],
+                                "navigationProperty": [
+                                    {
+                                        "name": "Category",
+                                        "toRole": "Category_Products",
+                                        "fromRole": "Product_Category",
+                                        "relationship": "ODataDemo.Product_Category_Category_Products"
+                                    }]
+                            },
+                            {
+                                "name": "FeaturedProduct",
+                                "baseType": "ODataDemo.Product",
+                                "navigationProperty": [
+                                    {
+                                        "name": "Advertisement",
+                                        "toRole": "Advertisement_FeaturedProduct",
+                                        "fromRole": "FeaturedProduct_Advertisement",
+                                        "relationship": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"
+                                    }
+                                ]
+                            },
+                            {
+                                "name": "Advertisement",
+                                "key": {
+                                    "propertyRef": [
+                                        {
+                                            "name": "ID"
+                                        }
+                                    ]
+                                },
+                                "property": [
+                                    {
+                                        "name": "ID",
+                                        "nullable": "false",
+                                        "type": "Edm.Guid"
+                                    }
+                                ],
+                                "navigationProperty": [
+                                    {
+                                        "name": "FeaturedProduct",
+                                        "toRole": "FeaturedProduct_Advertisement",
+                                        "fromRole": "Advertisement_FeaturedProduct",
+                                        "relationship": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"
+                                    }
+                                ]
+                            },
+                            {
+                                "name": "Category",
+                                "key": {
+                                    "propertyRef": [
+                                        {
+                                            "name": "ID"
+                                        }
+                                    ]
+                                },
+                                "property": [
+                                    {
+                                        "name": "ID",
+                                        "nullable": "false",
+                                        "type": "Edm.Int32"
+                                    }
+                                ],
+                                "navigationProperty": [
+                                    {
+                                        "name": "Products",
+                                        "toRole": "Product_Category",
+                                        "fromRole": "Category_Products",
+                                        "relationship": "ODataDemo.Product_Category_Category_Products"
+                                    }
+                                ]
+                            }
+                        ],
+                        "association": [
+                            {
+                                "name": "Product_Category_Category_Products",
+                                "end": [
+                                    {
+                                        "type": "ODataDemo.Category",
+                                        "multiplicity": "0..1",
+                                        "role": "Category_Products"
+                                    },
+                                    {
+                                        "type": "ODataDemo.Product",
+                                        "multiplicity": "*",
+                                        "role": "Product_Category"
+                                    }
+                                ]
+                            },
+                            {
+                                "name": "FeaturedProduct_Advertisement_Advertisement_FeaturedProduct",
+                                "end": [
+                                    {
+                                        "type": "ODataDemo.Advertisement",
+                                        "multiplicity": "0..1",
+                                        "role": "Advertisement_FeaturedProduct"
+                                    },
+                                    {
+                                        "type": "ODataDemo.FeaturedProduct",
+                                        "multiplicity": "0..1",
+                                        "role": "FeaturedProduct_Advertisement"
+                                    }
+                                ]
+                            }
+                        ],
+                        "entityContainer": [
+                            {
+                                "name": "DemoService",
+                                "isDefaultEntityContainer": "true",
+                                "entitySet": [
+                                    {
+                                        "name": "Products",
+                                        "entityType": "ODataDemo.Product"
+                                    },
+                                    {
+                                        "name": "Advertisements",
+                                        "entityType": "ODataDemo.Advertisement"
+                                    },
+                                    {
+                                        "name": "Categories",
+                                        "entityType": "ODataDemo.Category"
+                                    }
+                                ],
+                                "associationSet": [
+                                    {
+                                        "name": "Products_Advertisement_Advertisements",
+                                        "association": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct",
+                                        "end": [
+                                            {
+                                                "role": "FeaturedProduct_Advertisement",
+                                                "entitySet": "Products"
+                                            },
+                                            {
+                                                "role": "Advertisement_FeaturedProduct",
+                                                "entitySet": "Advertisements"
+                                            }
+                                        ]
+                                    },
+                                    {
+                                        "name": "Products_Category_Categories",
+                                        "association": "ODataDemo.Product_Category_Category_Products",
+                                        "end": [
+                                            {
+                                                "role": "Product_Category",
+                                                "entitySet": "Products"
+                                            },
+                                            {
+                                                "role": "Category_Products",
+                                                "entitySet": "Categories"
+                                            }
+                                        ]
+                                    }
+                                ]
+                            }
+                        ]
+                    }
+                ]
+            }
+        };
+    };
+
+    var failTest = function (err) {
+        if (err && err.message) {
+            djstest.fail(err.message);
+        } else {
+            djstest.fail("unexpected failure");
+        }
+        djstest.done();
+    };
+
+    var verifySerializedJsonLightData = function (actual, expected, message, requestUri) {
+        mockHttpClient.addRequestVerifier("*", function (request) {
+            djstest.assertAreEqualDeep(JSON.parse(request.body), expected, message);
+            djstest.done();
+        });
+
+        odatajs.oData.request({
+            requestUri: requestUri || "http://someUri",
+            headers: { "Content-Type": "application/json" },
+            method: "PUT",
+            data: actual
+        }, null, failTest, null, mockHttpClient);
+    };
+
+    var verifyReadJsonLightData = function (input, expected, message, model) {
+        var response = { headers: { "Content-Type": "application/json;odata.metadata=full", DataServiceVersion: "4.0" }, body: JSON.stringify(input) };
+
+        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
+        djstest.assertAreEqualDeep(response.data, expected, message);
+    };
+
+    var verifyReadJsonLightWithMinimalMetadata = function (input, expected, message, model) {
+        var response = { headers: { "Content-Type": "application/json;odata.metadata=minimal", DataServiceVersion: "4.0" }, body: JSON.stringify(input) };
+
+        OData.jsonHandler.read(response, { metadata: model });
+        djstest.assertAreEqualDeep(response.data, expected, message);
+    };
+
+
+    djstest.addTest(function jsonLightReadEmptySvcDocTest() {
+        var input = {
+            "odata.metadata": "http://someUri/ODataService.svc/OData/$metadata",
+            "value": []
+        };
+
+        var expected = {
+            workspaces: [
+                {
+                    collections: []
+                }
+            ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadSvcDocTest() {
+        var input = {
+            "odata.metadata": "http://someUri/ODataService.svc/OData/$metadata",
+            "value": [
+                { "name": "Customers", "url": "Customers" },
+                { "name": "Employees", "url": "http://someUri/ODataService.svc/OData/Employees" }
+            ]
+        };
+
+        var expected = {
+            workspaces: [
+                {
+                    collections: [
+                        {
+                            title: "Customers",
+                            href: "http://someUri/ODataService.svc/OData/Customers"
+                        },
+                        {
+                            title: "Employees",
+                            href: "http://someUri/ODataService.svc/OData/Employees"
+                        }
+                    ]
+                }
+            ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryMetadataUriTest() {
+        var tests = {
+            "Qualified entity set": {
+                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/@Element" },
+                expected: { __metadata: { type: null} }
+            },
+            "Unqualified entity set": {
+                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/@Element" },
+                expected: { __metadata: { type: null} }
+            },
+            "Qualified entity set with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/TypeCast/@Element" },
+                expected: { __metadata: { type: "TypeCast"} }
+            },
+
+            "Unqualified entity set with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#EntitySet/TypeCast/@Element" },
+                expected: { __metadata: { type: "TypeCast"} }
+            }
+        };
+
+        for (name in tests) {
+            var test = tests[name];
+            verifyReadJsonLightData(test.input, test.expected, name + " - Json light entry metadata uri was read properly.");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryMetadataUriWithMetadataDocumentTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Test.Catalog",
+                    "entityContainer": [{
+                        "name": "TestCatalog",
+                        "isDefaultEntityContainer": "true",
+                        "entitySet": [
+                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
+                    ]
+                    }, {
+                        "name": "GenreCatalog",
+                        "isDefaultEntityContainer": "false",
+                        "entitySet": [
+                           { "name": "Genres", "entityType": "TestCatalog.Model.Genre" }
+                    ]
+                    }]
+                }]
+            }
+        };
+
+        var tests = {
+            "Qualified entity set": {
+                input: { "odata.metadata": "http://someUri/$metadata#Test.Catalog.GenreCatalog.Genres/@Element" },
+                expected: { __metadata: { type: "TestCatalog.Model.Genre"} }
+            },
+            "Unqualified entity set": {
+                input: { "odata.metadata": "http://someUri/$metadata#Titles/@Element" },
+                expected: { __metadata: { type: "TestCatalog.Model.Title"} }
+            },
+            "Qualified entity set with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#Test.Catalog.Titles/TestCatalog.Model.Songs/@Element" },
+                expected: { __metadata: { type: "TestCatalog.Model.Songs"} }
+            },
+            "Unqualified entity set with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#Titles/TestCatalog.Model.Songs/@Element" },
+                expected: { __metadata: { type: "TestCatalog.Model.Songs"} }
+            },
+            "Unqualified entity set in non default entity container": {
+                input: { "odata.metadata": "http://someUri/$metadata#Generes/@Element" },
+                expected: { __metadata: { type: null} }
+            },
+            "Unqualified entity set in non default entity container with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#Generes/TypeCast/@Element" },
+                expected: { __metadata: { type: "TypeCast"} }
+            }
+        };
+
+        for (name in tests) {
+            var test = tests[name];
+            verifyReadJsonLightData(test.input, test.expected, name + " - Json light entry metadata uri was read properly.", testModel);
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTypeInPayloadWinsOverModelTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "NS",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "hasStream": "true",
+                        "key": { "propertyRef": [{ "name": "Id"}] },
+                        "property": [
+                                { "name": "Id", "type": "Edm.String" },
+                                { "name": "P1", "type": "Edm.String" },
+                                { "name": "P2", "type": "NS.ComplexType" },
+                                { "name": "P3", "type": "Edm.Int64" }
+                            ]
+                    }],
+                    "complexType": [{
+                        "name": "ComplexType",
+                        "property": [
+                            { "name": "C1", "type": "Edm.String" }
+                        ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/NS.EntityType/@Element",
+            P1: "Hello",
+            P2: {
+                "odata.type": "Instance",
+                C1: "World"
+            },
+            "P2@odata.type": "Property",
+            P3: "500",
+            "P3@odata.type": "Property",
+            P4: {
+                "odata.type": "NS.ComplexType",
+                C1: "!!"
+            }
+        };
+
+        var expected = {
+            __metadata: {
+                type: "NS.EntityType",
+                properties: {
+                    P1: { type: "Edm.String" },
+                    P2: {
+                        type: "Instance",
+                        properties: {
+                            C1: { type: null }
+                        }
+                    },
+                    P3: { type: "Property" },
+                    P4: {
+                        type: "NS.ComplexType",
+                        properties: {
+                            C1: { type: "Edm.String" }
+                        }
+                    }
+                }
+            },
+            P1: "Hello",
+            P2: {
+                __metadata: {
+                    type: "Instance"
+                },
+                C1: "World"
+            },
+            P3: "500",
+            P4: {
+                __metadata: {
+                    type: "NS.ComplexType"
+                },
+                C1: "!!"
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadObjectWithCollectionPropertyTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "NS",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "property": [
+                                { "name": "p1", "type": "Collection(Edm.Int32)" }
+                            ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/NS.EntityType/@Element",
+            p1: [1, 2, 3],
+            p2: [
+                { c1: 100, c2: 200 },
+                { c1: 400, c2: 500, "odata.type": "NS.OtherType" }
+            ],
+            "p2@odata.type": "Collection(NS.ComplexType)",
+            p3: [5, 6, 7]
+        };
+
+        var expected = {
+            __metadata: {
+                type: "NS.EntityType",
+                properties: {
+                    p1: { type: "Collection(Edm.Int32)" },
+                    p2: {
+                        type: "Collection(NS.ComplexType)",
+                        elements: [
+                            {
+                                type: "NS.ComplexType",
+                                properties: {
+                                    c1: { type: null },
+                                    c2: { type: null }
+                                }
+                            },
+                            {
+                                type: "NS.OtherType",
+                                properties: {
+                                    c1: { type: null },
+                                    c2: { type: null }
+                                }
+                            }
+                        ]
+                    },
+                    p3: { type: null }
+                }
+            },
+            p1: {
+                __metadata: { type: "Collection(Edm.Int32)" },
+                results: [1, 2, 3]
+            },
+            p2: {
+                __metadata: { type: "Collection(NS.ComplexType)" },
+                results: [
+                    {
+                        __metadata: {
+                            type: "NS.ComplexType"
+                        },
+                        c1: 100,
+                        c2: 200
+                    },
+                    {
+                        __metadata: {
+                            type: "NS.OtherType"
+                        },
+                        c1: 400,
+                        c2: 500
+                    }
+                ]
+            },
+            p3: {
+                __metadata: { type: null },
+                results: [5, 6, 7]
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with collection porperties was read properly", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryODataAnnotationsTest() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
+            "odata.id": "Customers(1)",
+            "odata.etag": "etag-value",
+            "odata.readLink": "read/Customers(1)",
+            "odata.editLink": "Customers(1)",
+            "odata.mediaReadLink": "Customers(1)/Image",
+            "odata.mediaEditLink": "Customers(1)/$value",
+            "odata.mediaETag": "stream-etag-value",
+            "odata.mediaContentType": "image/jpg"
+        };
+
+        var expected = {
+            __metadata: {
+                id: "Customers(1)",
+                type: "TypeCast",
+                etag: "etag-value",
+                self: "http://someUri/read/Customers(1)",
+                edit: "http://someUri/Customers(1)",
+                uri: "http://someUri/Customers(1)",
+                media_src: "http://someUri/Customers(1)/Image",
+                edit_media: "http://someUri/Customers(1)/$value",
+                media_etag: "stream-etag-value",
+                content_type: "image/jpg"
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light entry OData annotations were read properly");
+        djstest.done();
+    });
+
+
+    djstest.addTest(function jsonLightReadObjectWithComplexPropertyTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "property": [
+                                { "name": "p1", "type": "Ns.ComplexType" }
+                         ]
+                    }],
+                    "complexType": [{
+                        "name": "ComplexType",
+                        "property": [
+                            { "name": "c1", "type": "Edm.Int16" },
+                            { "name": "c2", "type": "Edm.Int32" },
+                            { "name": "c3", "type": "Ns.ComplexType" }
+                        ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
+            p1: {
+                c1: 100,
+                c2: 200,
+                c3: {
+                    c1: 300,
+                    c2: 400,
+                    c3: {
+                        c1: 500,
+                        c2: 600,
+                        c3: null
+                    }
+                }
+            },
+            p2: {
+                "odata.type": "Ns.ComplexType2",
+                c4: 800,
+                "c4@odata.type": "Edm.Single",
+                c5: 900,
+                c6: {
+                    c1: 1000,
+                    c2: 2000,
+                    c3: {
+                        c1: 1100,
+                        "c1@odata.type": "Edm.Double",
+                        c2: 1200,
+                        c3: null
+                    }
+                },
+                "c6@odata.type": "Ns.ComplexType"
+            },
+            p3: {},
+            "p3@odata.type": "Ns.ComplexType3"
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Ns.EntityType",
+                properties: {
+                    p1: {
+                        type: "Ns.ComplexType",
+                        properties: {
+                            c1: { type: "Edm.Int16" },
+                            c2: { type: "Edm.Int32" },
+                            c3: {
+                                type: "Ns.ComplexType",
+                                properties: {
+                                    c1: { type: "Edm.Int16" },
+                                    c2: { type: "Edm.Int32" },
+                                    c3: {
+                                        type: "Ns.ComplexType",
+                                        properties: {
+                                            c1: { type: "Edm.Int16" },
+                                            c2: { type: "Edm.Int32" },
+                                            c3: { type: "Ns.ComplexType" }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    p2: {
+                        type: "Ns.ComplexType2",
+                        properties: {
+                            c4: { type: "Edm.Single" },
+                            c5: { type: null },
+                            c6: {
+                                type: "Ns.ComplexType",
+                                properties: {
+                                    c1: { type: "Edm.Int16" },
+                                    c2: { type: "Edm.Int32" },
+                                    c3: {
+                                        type: "Ns.ComplexType",
+                                        properties: {
+                                            c1: { type: "Edm.Double" },
+                                            c2: { type: "Edm.Int32" },
+                                            c3: { type: "Ns.ComplexType" }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    p3: { type: "Ns.ComplexType3" }
+                }
+            },
+            p1: {
+                __metadata: { type: "Ns.ComplexType" },
+                c1: 100,
+                c2: 200,
+                c3: {
+                    __metadata: { type: "Ns.ComplexType" },
+                    c1: 300,
+                    c2: 400,
+                    c3: {
+                        __metadata: { type: "Ns.ComplexType" },
+                        c1: 500,
+                        c2: 600,
+                        c3: null
+                    }
+                }
+            },
+            p2: {
+                __metadata: { type: "Ns.ComplexType2" },
+                c4: 800,
+                c5: 900,
+                c6: {
+                    __metadata: { type: "Ns.ComplexType" },
+                    c1: 1000,
+                    c2: 2000,
+                    c3: {
+                        __metadata: { type: "Ns.ComplexType" },
+                        c1: 1100,
+                        c2: 1200,
+                        c3: null
+                    }
+                }
+            },
+            p3: { __metadata: { type: "Ns.ComplexType3"} }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with complex type properties was read properly", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadObjectWithNamedStreamProperty() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
+            "p1@odata.mediaReadLink": "Customers(1)/namedStream",
+            "p1@odata.mediaEditLink": "Customers(1)/namedStream/$value",
+            "p1@odata.mediaETag": "voice-etag-value",
+            "p1@odata.mediaContentType": "audio/basic"
+        };
+
+        var expected = {
+            __metadata: {
+                type: "TypeCast",
+                properties: {
+                    p1: { type: null }
+                }
+            },
+            p1: {
+                __mediaresource: {
+                    media_src: "http://someUri/Customers(1)/namedStream",
+                    edit_media: "http://someUri/Customers(1)/namedStream/$value",
+                    media_etag: "voice-etag-value",
+                    content_type: "audio/basic"
+                }
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with named stream properties was read properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryWithDeferredNavigationPropertyTests() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
+            "p1@odata.navigationLinkUrl": "entitySet(1)/deferred",
+            "p1@odata.associationLinkUrl": "entitySet(1)/$links/deferred"
+        };
+
+        var expected = {
+            __metadata: {
+                type: "TypeCast",
+                properties: {
+                    p1: {
+                        type: null,
+                        associationLinkUrl: "http://someUri/entitySet(1)/$links/deferred"
+                    }
+                }
+            },
+            p1: {
+                __deferred: {
+                    uri: "http://someUri/entitySet(1)/deferred"
+                }
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with deferred navigation properties was read properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryWithInlinedNavigationPropertiesTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "navigationProperty": [
+                            { "name": "p1", "relationship": "Ns.Rel1", "toRole": "p1s" },
+                            { "name": "p2", "relationship": "Ns.Rel2", "toRole": "p2s" }
+                        ]
+                    }],
+                    "association": [{
+                        "name": "Rel1",
+                        "end": [
+                            { "type": "Ns.EntityType1", "role": "p1s" },
+                            { "type": "Ns.EntityType", "role": "otherRole" }
+                         ]
+                    },
+                    {
+                        "name": "Rel2",
+                        "end": [
+                            { "type": "Ns.EntityType", "role": "otherRole" },
+                            { "type": "Ns.EntityType2", "role": "p2s" }
+                         ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
+            p1: [
+                { e1: 100, e2: 200 },
+                { e1: 110, e2: 220 }
+            ],
+            "p1@odata.count": 50,
+            "p1@odata.nextLink": "nextToken",
+            p2: {
+                e3: 300
+            },
+            p3: [
+                { e4: 400, e5: 500 },
+                { e4: 440, e5: 550 }
+            ],
+            "p3@odata.navigationLinkUrl": "http://someUri/entitySet(1)/p3",
+            "p3@odata.associationLinkUrl": "http://someUri/entitySet(1)/$links/p3",
+            p4: {
+                e6: 600
+            },
+            "p4@odata.navigationLinkUrl": "http://someUri/entitySet(1)/p4",
+            "p4@odata.associationLinkUrl": "http://someUri/entitySet(1)/$links/p4",
+            p5: [
+                {
+                    "odata.id": 12345,
+                    e7: 700,
+                    e8: 800
+                }
+            ],
+            p6: {
+                "odata.id": 78910,
+                e9: 900,
+                "e9@odata.type": "Edm.Int32"
+            }
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Ns.EntityType",
+                properties: {
+                    p1: {
+                        type: "Ns.EntityType1"
+                    },
+                    p2: {
+                        type: "Ns.EntityType2"
+                    },
+                    p3: {
+                        type: null,
+                        navigationLinkUrl: "http://someUri/entitySet(1)/p3",
+                        associationLinkUrl: "http://someUri/entitySet(1)/$links/p3"
+                    },
+                    p4: {
+                        type: null,
+                        navigationLinkUrl: "http://someUri/entitySet(1)/p4",
+                        associationLinkUrl: "http://someUri/entitySet(1)/$links/p4"
+                    },
+                    p5: {
+                        type: null
+                    },
+                    p6: {
+                        type: null
+                    }
+                }
+            },
+            p1: {
+                __count: 50,
+                __next: "http://someUri/nextToken",
+                results: [
+            {
+                __metadata: {
+                    type: "Ns.EntityType1",
+                    properties: {
+                        e1: { type: null },
+                        e2: { type: null }
+                    }
+                },
+                e1: 100,
+                e2: 200
+            },
+            {
+                __metadata: {
+                    type: "Ns.EntityType1",
+                    properties: {
+                        e1: { type: null },
+                        e2: { type: null }
+                    }
+                },
+                e1: 110,
+                e2: 220
+            }
+          ]
+            },
+            p2: {
+                __metadata: {
+                    type: "Ns.EntityType2",
+                    properties: {
+                        e3: { type: null }
+                    }
+                },
+                e3: 300
+            },
+            p3: {
+                results: [
+            {
+                __metadata: {
+                    type: null,
+                    properties: {
+                        e4: { type: null },
+                        e5: { type: null }
+                    }
+                },
+                e4: 400,
+                e5: 500
+            },
+            {
+                __metadata: {
+                    type: null,
+                    properties: {
+                        e4: { type: null },
+                        e5: { type: null }
+                    }
+                },
+                e4: 440,
+                e5: 550
+            }
+            ]
+            },
+            p4: {
+                __metadata: {
+                    type: null,
+                    properties: {
+                        e6: { type: null }
+                    }
+                },
+                e6: 600
+            },
+            p5: {
+                results: [
+                {
+                    __metadata: {
+                        id: 12345,
+                        type: null,
+                        properties: {
+                            e7: { type: null },
+                            e8: { type: null }
+                        }
+                    },
+                    e7: 700,
+                    e8: 800
+                }
+            ]
+            },
+            p6: {
+                __metadata: {
+                    id: 78910,
+                    type: null,
+                    properties: {
+                        e9: { type: "Edm.Int32" }
+                    }
+                },
+                e9: 900
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with inlined navigation properties was read properly", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadStringPropertiesTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "property": [
+                                { "name": "p1", "type": "Edm.DateTime" },
+                                { "name": "p2", "type": "Edm.DateTimeOffset" },
+                                { "name": "p3", "type": "Edm.Time" }
+                            ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
+            p1: "2000-01-02T03:04:05",
+            p2: "2000-01-02T03:04:05+01:00",
+            p3: "P0Y0M05DT12H30M5S",
+            p4: "hello world",
+            p5: "2001-01-02T03:04:05",
+            "p5@odata.type": "Edm.DateTime",
+            p6: "2001-01-02T03:04:05+01:00",
+            "p6@odata.type": "Edm.DateTimeOffset",
+            p7: "P0Y0M05DT12H30M10S",
+            "p7@odata.type": "Edm.Time"
+        };
+
+        var p2 = new Date("01/02/2000 02:04:05 GMT");
+        p2.__edmType = "Edm.DateTimeOffset";
+        p2.__offset = "+01:00";
+
+        var p6 = new Date("01/02/2001 02:04:05 GMT");
+        p2.__edmType = "Edm.DateTimeOffset";
+        p2.__offset = "+01:00";
+
+        var expected = {
+            __metadata: {
+                type: "Ns.EntityType",
+                properties: {
+                    p1: { type: "Edm.DateTime" },
+                    p2: { type: "Edm.DateTimeOffset" },
+                    p3: { type: "Edm.Time" },
+                    p4: { type: null },
+                    p5: { type: "Edm.DateTime" },
+                    p6: { type: "Edm.DateTimeOffset" },
+                    p7: { type: "Edm.Time" }
+                }
+            },
+            p1: new Date("01/02/2000 03:04:05 GMT"),
+            p3: { ms: 477005000, __edmType: "Edm.Time" },
+            p2: p2,
+            p4: "hello world",
+            p5: new Date("01/02/2001 03:04:05 GMT"),
+            p6: p6,
+            p7: { ms: 477010000, __edmType: "Edm.Time" }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with string properties was read properly", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadRecognizeDateLiteralsTest() {
+        var input = {
+            p1: "2000-01-02T03:04:05",
+            p2: "2000-01-02T03:04:05+01:00"
+        };
+
+        var p2 = new Date("01/02/2000 02:04:05 GMT");
+        p2.__edmType = "Edm.DateTimeOffset";
+        p2.__offset = "+01:00";
+
+        var expected = {
+            __metadata: {
+                properties: {
+                    p1: {
+                        type: null
+                    },
+                    p2: {
+                        type: null
+                    }
+                },
+                type: null
+            },
+            p1: new Date("01/02/2000 03:04:05 GMT"),
+            p2: p2
+        };
+
+        OData.jsonHandler.recognizeDates = true;
+        verifyReadJsonLightData(input, expected, "Json light datetime literals were recognized. ");
+
+        OData.jsonHandler.recognizeDates = false;
+
+        expected.p1 = input.p1;
+        expected.p2 = input.p2;
+
+        verifyReadJsonLightData(input, expected, "Json light datetime literals were ignored");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEmptyFeedTest() {
+        var input = { "odata.metadata": "http://someUri#entitySet/Set", value: [] };
+        var expected = { results: [] };
+
+        verifyReadJsonLightData(input, expected, "Json light feed object was read properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadFeedTest() {
+        var input = {
+            "odata.metadata": "http://someUri#entitySet/Type",
+            value: [
+              { "odata.id": 12345 },
+              { "odata.id": 56789 }
+            ],
+            "odata.count": 50,
+            "odata.nextLink": "skipToken"
+        };
+
+        var expected = {
+            __count: 50,
+            __next: "http://someUri/skipToken",
+            results: [
+                {
+                    __metadata: {
+                        id: 12345,
+                        type: "Type"
+                    }
+                },
+                {
+                    __metadata: {
+                        id: 56789,
+                        type: "Type"
+                    }
+                }
+            ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light feed object was read properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadFeedUsingMetadataTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Test.Catalog",
+                    "entityContainer": [{
+                        "name": "TestCatalog",
+                        "isDefaultEntityContainer": "true",
+                        "entitySet": [
+                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
+                        ]
+                    }
+                    ]
+                }
+                ]
+            }
+        };
+
+        var tests = {
+            "Unqualified entity set": {
+                input: { "odata.metadata": "http://someUri#Titles", value: [{}] },
+                expected: { results: [{ __metadata: { type: "TestCatalog.Model.Title"}}] }
+            },
+            "Qualified entity set": {
+                input: { "odata.metadata": "http://someUri#Test.Catalog.TestCatalog.Titles", value: [{}] },
+                expected: { results: [{ __metadata: { type: "TestCatalog.Model.Title"}}] }
+            },
+            "Type casted entity set": {
+                input: { "odata.metadata": "http://someUri#TestCatalog.Titles/TypeCast", value: [{}] },
+                expected: { results: [{ __metadata: { type: "TypeCast"}}] }
+            }
+        };
+
+        for (var name in tests) {
+            var test = tests[name];
+            verifyReadJsonLightData(test.input, test.expected, name + " - Json light feed was read properly.", testModel);
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadInferFeedAsObjectTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Test.Catalog",
+                    "entityContainer": [{
+                        "name": "TestCatalog",
+                        "isDefaultEntityContainer": "true",
+                        "entitySet": [
+                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
+                        ]
+                    }
+                    ]
+                }
+                ]
+            }
+        };
+
+        var tests = {
+            "Feed as object": {
+                input: { "odata.metadata": "http://someUri#EntitySet", value: [] },
+                expected: {
+                    __metadata: {
+                        type: "EntitySet",
+                        properties: {
+                            value: { type: null }
+                        }
+                    },
+                    value: { __metadata: { type: null }, results: [] }
+                }
+            },
+            "Feed as feed using value": {
+                input: { "odata.metadata": "http://someUri#EntiySet", value: [{ "odata.id": 12345}] },
+                expected: { results: [{ __metadata: { type: null, id: 12345}}] }
+            },
+            "Feed as feed using metadata": {
+                input: { "odata.metadata": "http://someUri#Titles", value: [] },
+                expected: { results: [] }
+            },
+            "Collection of primitive": {
+                input: { "odata.metadata": "http://someUri#Collection(Edm.Int32)", value: [] },
+                expected: { __metadata: { type: "Collection(Edm.Int32)" }, results: [] }
+            },
+            "Collection of complex": {
+                input: { "odata.metadata": "http://someUri#Collection(My.Type)", value: [] },
+                expected: { __metadata: { type: "Collection(My.Type)" }, results: [] }
+            }
+        };
+
+        for (var name in tests) {
+            var test = tests[name];
+            var response = {
+                headers: {
+                    "Content-Type": "application/json;odata.metadata=full",
+                    DataServiceVersion: "4.0"
+                },
+                body: JSON.stringify(test.input)
+            };
+
+            OData.jsonHandler.read(response, { metadata: testModel });
+            djstest.assertAreEqualDeep(response.data, test.expected, name + " - Json light object was read properly ");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEmptyLinksDocumentTest() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp",
+            value: []
+        };
+
+        var expected = {
+            results: []
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadLinksDocumentTest() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp",
+            value: [
+                        { url: "Products(1)" },
+                        { url: "http://someUri/Products(2)" }
+                     ]
+        };
+
+        var expected = {
+            results: [
+                        { uri: "http://someUri/Products(1)" },
+                        { uri: "http://someUri/Products(2)" }
+                    ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadSingleLinkDocumentTest() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp/@Element",
+            url: "Products(1)"
+        };
+
+        var expected = {
+            uri: "http://someUri/Products(1)"
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light single link document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTopLevelPrimitiveProperty() {
+        var input = {
+            "odata.metadata": "http://someUri#Edm.GeometryPoint",
+            value: {
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: name,
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+            }
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Edm.GeometryPoint"
+            },
+            value: {
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: name,
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light top level primitive property was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTopLevelComplexTypeTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "complexType": [{
+                        "name": "ComplexType",
+                        "property": [
+                            { "name": "value", "type": "Collection(Ns.ComplexType2)" }
+                        ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri#Ns.ComplexType",
+            value: [{
+                p1: 100,
+                p2: 200
+            }]
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Ns.ComplexType",
+                properties: {
+                    value: {
+                        type: "Collection(Ns.ComplexType2)",
+                        elements: [
+                            {
+                                type: "Ns.ComplexType2",
+                                properties: {
+                                    p1: { type: null },
+                                    p2: { type: null }
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            value: {
+                __metadata: { type: "Collection(Ns.ComplexType2)" },
+                results: [
+                    {
+                        __metadata: { type: "Ns.ComplexType2" },
+                        p1: 100,
+                        p2: 200
+                    }
+                ]
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light top level complex type property was read properly.", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTopPrimitiveCollectionPropertyTest() {
+        var input = {
+            "odata.metadata": "http://someUri#Collection(Edm.GeometryPoint)",
+            value: [{
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: "name",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+            }]
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Collection(Edm.GeometryPoint)"
+            },
+            results: [{
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: "name",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+            }]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light top level primitive collection property was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTopLevelComplexTypeCollectionTest() {
+        var input = {
+            "odata.metadata": "http://someUri#Collection(Ns.ComplexType2)",
+            value: [{
+                p1: 100,
+                p2: 200,
+                "p2@odata.type": "Edm.Int16"
+            }]
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Collection(Ns.ComplexType2)",
+                elements: [
+                    {
+                        type: "Ns.ComplexType2",
+                        properties: {
+                            p1: { type: null },
+                            p2: { type: "Edm.Int16" }
+                        }
+                    }
+                ]
+            },
+            results: [
+                {
+                    __metadata: { type: "Ns.ComplexType2" },
+                    p1: 100,
+                    p2: 200
+                }
+             ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light top level complex type collection property was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadFeedAdvertisedActionsTest() {
+
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "entityContainer": [{
+                        "name": "EntityContainer",
+                        "isDefaultEntityContainer": "true",
+                        "entitySet": [
+                           { "name": "EntitySet", "entityType": "Ns.EntityType" }
+                        ]
+                    }
+                    ]
+                }
+                ]
+            }
+        };
+
+        input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet",
+            "#action1": {
+                target: "action1/item(0)",
+                title: "Action1"
+            },
+            "#action2": {
+                target: "action2/item(0)",
+                title: "Action2"
+            },
+            value: []
+        };
+
+        expected = {
+            __metadata: {
+                actions: [
+                    {
+                        metadata: "http://someUri/action1",
+                        target: "http://someUri/action1/item(0)",
+                        title: "Action1"
+                    },
+                   {
+                       metadata: "http://someUri/action2",
+                       target: "http://someUri/action2/item(0)",
+                       title: "Action2"
+                   }
+                ]
+            },
+            results: []
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light feed with advertised actions was read properly.", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadAdvertisedActionsAndFunctionsTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Test.Catalog",
+                    "entityContainer": [{
+                        "name": "TestCatalog",
+                        "isDefaultEntityContainer": "true",
+                        "functionImport": [
+                            { "name": "function1", "isSideEffecting": "false" },
+                            { "name": "function2", "isSideEffecting": "false" },
+                            { "name": "action1", "isSideEffecting": "true" },
+                            { "name": "action2" }
+                         ]
+                    }, {
+                        "name": "OtherCatalog",
+                        "isDefaultEntityContainer": "false",
+                        "functionImport": [
+                            { "name": "function1", "isSideEffecting": "false" }
+                         ]
+                    }]
+                }]
+            }
+        };
+
+        input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/@Element",
+            "#function2": [
+                {
+                    target: "function2/item(0)",
+                    title: "Function2 overload1"
+                },
+                {
+                    target: "function2/item(0)",
+                    title: "Function2 overload2"
+                }
+            ],
+            "#action1": {
+                target: "action1/item(0)",
+                title: "Action1"
+            },
+            "#action2": {
+                target: "action2/item(0)",
+                title: "Action2"
+            },
+            "#function1": {
+                target: "function1/item(0)",
+                title: "Function1"
+            },
+            "#Test.Catalog.OtherCatalog.function1": {
+                target: "Test.Catalog.OtherCatalog.function1/item(0)",
+                title: "Function1 in other catalog"
+            },
+            "#action3": [
+                {
+                    target: "action3/item(0)",
+                    title: "Unkown action overload1"
+                },
+                {
+                    target: "http://otherUri/action3/item(0)",
+                    title: "Unkown action overload2"
+                }
+            ]
+        };
+
+        expected = {
+            __metadata: {
+                type: null,
+                actions: [
+                   {
+                       metadata: "http://someUri/action1",
+                       target: "http://someUri/action1/item(0)",
+                       title: "Action1"
+                   },
+                   {
+                       metadata: "http://someUri/action2",
+                       target: "http://someUri/action2/item(0)",
+                       title: "Action2"
+                   },
+                   {
+                       metadata: "http://someUri/action3",
+                       target: "http://someUri/action3/item(0)",
+                       title: "Unkown action overload1"
+                   },
+                   {
+                       metadata: "http://someUri/action3",
+                       target: "http://otherUri/action3/item(0)",
+                       title: "Unkown action overload2"
+                   }
+                ],
+                functions: [
+                    {
+                        metadata: "http://someUri/function2",
+                        target: "http://someUri/function2/item(0)",
+                        title: "Function2 overload1"
+                    },
+                    {
+                        metadata: "http://someUri/function2",
+                        target: "http://someUri/function2/item(0)",
+                        title: "Function2 overload2"
+                    },
+                    {
+                        metadata: "http://someUri/function1",
+                        target: "http://someUri/function1/item(0)",
+                        title: "Function1"
+                    },
+                    {
+                        metadata: "http://someUri/Test.Catalog.OtherCatalog.function1",
+                        target: "http://someUri/Test.Catalog.OtherCatalog.function1/item(0)",
+                        title: "Function1 in other catalog"
+                    }
+                ]
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light advertised actions and functions were read properly.", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryMetadataTest() {
+        var data = {
+            __metadata: {
+                metadata: "http://someUri/$metadata#NS.Container/Set/@Element",
+                id: "http://someUri/Customers(1)",
+                etag: "etag-value",
+                self: "http://someUri/read/Customers(1)",
+                edit: "http://someUri/read/Customers(1)",
+                media_src: "http://someUri/Customers(1)/Image",
+                edit_media: "http://someUri/Customers(1)/$value",
+                media_etag: "stream-etag-value",
+                content_type: "image/jpg"
+            }
+        };
+
+        var expected = {
+            "odata.etag": "etag-value",
+            "odata.mediaReadLink": "http://someUri/Customers(1)/Image",
+            "odata.mediaEditLink": "http://someUri/Customers(1)/$value",
+            "odata.mediaETag": "stream-etag-value",
+            "odata.mediaContentType": "image/jpg"
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry metadata was serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeCustomAnnotationsTest() {
+        var data = {
+            __metadata: {
+                id: "id"
+            },
+            "odata.id": "id",
+            "custom.annotation": "custom annotation value",
+            "p1@ns1.primitive": "primitive",
+            "p1@ns2.complex": { a1: 500 },
+            "p1@ns3.ns4.value": 600,
+            "p2@ns1.primitive": 400,
+            "custom.annotation": "custom annotation value"
+        };
+
+        var expected = {
+            "odata.id": "id",
+            "custom.annotation": "custom annotation value",
+            "p1@ns1.primitive": "primitive",
+            "p1@ns2.complex": { a1: 500 },
+            "p1@ns3.ns4.value": 600,
+            "p2@ns1.primitive": 400
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light custom annotations were serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryCollectionPropertiesTest() {
+        var data = {
+            __metadata: {
+                id: "id",
+                properties: {
+                    primitiveColArray: { type: "Collection(Edm.Int16)" },
+                    primitiveColObject: { type: "Collection(Edm.Int32)" }
+                }
+            },
+            primitiveColArray: [1, 2, 3, 4],
+            primitiveColObject: {
+                results: [5, 6, 7, 8]
+            },
+            complexColArray: [{ p1: 100 }, { p1: 200}],
+            complexColObject: {
+                results: [{ p1: 300 }, { p1: 400}]
+            }
+        };
+
+        var expected = {
+            "primitiveColArray@odata.type": "Collection(Edm.Int16)",
+            primitiveColArray: [1, 2, 3, 4],
+            "primitiveColObject@odata.type": "Collection(Edm.Int32)",
+            primitiveColObject: [5, 6, 7, 8],
+            complexColArray: [{ p1: 100 }, { p1: 200}],
+            complexColObject: [{ p1: 300 }, { p1: 400}]
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry collection properties were serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryDeferredPropertyTest() {
+        var data = {
+            __metadata: {
+                id: "id",
+                properties: {
+                    deferred: {
+                        associationLinkUrl: "http://target/$links"
+                    }
+                }
+            },
+            deferred: {
+                __deferred: { uri: "http://target" }
+            }
+        };
+
+        var expected = {
+            "deferred@odata.navigationLinkUrl": "http://target"
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry deferred property were serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryInlinePropertiesTest() {
+        var data = {
+            __metadata: {
+                id: "id"
+            },
+            inlineEntry: {
+                __metadata: { uri: "", properties: { p1: { type: "Edm.Int64"}} },
+                p1: "300"
+            },
+            inlineBoundEntry: {
+                __metadata: { uri: "http://entries(1)", properties: { p1: { type: "Edm.Int64"}} },
+                p1: "400"
+            },
+            inlineFeedArray: [
+                {
+                    __metadata: { uri: "http://entries(2)" }
+                },
+                {
+                    __metadata: { uri: "", properties: { p1: { type: "Edm.Int32"}} },
+                    p1: "600"
+                },
+                {
+                    __metadata: { uri: "http://entries(3)" }
+                }
+            ],
+            inlineFeedObject: {
+                __count: 50,
+                __next: "next link",
+                results: [
+                    { __metadata: { uri: "" }, p1: "900" }
+                ]
+            },
+            inlineEmptyFeedObject: {
+                results: []
+            }
+        };
+
+        var expected = {
+            inlineEntry: {
+                "p1@odata.type": "Edm.Int64",
+                p1: "300"
+            },
+            "inlineBoundEntry@odata.bind": "http://entries(1)",
+            inlineFeedArray: [{
+                "p1@odata.type": "Edm.Int32",
+                p1: "600"
+            }],
+            "inlineFeedArray@odata.bind": [
+                "http://entries(2)",
+                "http://entries(3)"
+            ],
+            inlineFeedObject: [{
+                p1: "900"
+            }],
+            inlineEmptyFeedObject: []
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry inline properties were serialized properly.");
+
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryComplexPropertyTest() {
+        var data = {
+            __metadata: {
+                id: "id",
+                properties: {
+                    complexAsDeferredOnMetadata: {
+                        type: "complexAsDeferredOnMetadata.type"
+                    },
+                    complexAsCol: {
+                        type: "complexAsCol.type"
+                    }
+                }
+            },
+            complexAsDeferred: {
+                __metadata: {
+                    type: "complexAsDeferred.type"
+                },
+                __deferred: { uri: "http://uri" }
+            },
+            complexAsCol: {
+                results: [1, 2, 3, 4]
+            },
+            complexAsNamedStream: {
+                __metadata: {
+                    type: "complexAsNamedStream"
+                },
+                __mediaresource: {
+                    content_type: "content type",
+                    media_src: "http://source"
+                }
+            },
+            complexAsDeferredOnMetadata: {
+                __deferred: { uri: "http://uri2" }
+            }
+        };
+
+        var expected = {
+            complexAsDeferred: {
+                "odata.type": "complexAsDeferred.type",
+                __deferred: { uri: "http://uri" }
+            },
+            complexAsCol: {
+                "odata.type": "complexAsCol.type",
+                results: [1, 2, 3, 4]
+            },
+            complexAsNamedStream: {
+                "odata.type": "complexAsNamedStream",
+                __mediaresource: {
+                    content_type: "content type",
+                    media_src: "http://source"
+                }
+            },
+            complexAsDeferredOnMetadata: {
+                "odata.type": "complexAsDeferredOnMetadata.type",
+                __deferred: { uri: "http://uri2" }
+            }
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry complex properties were serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryComplexPropertyMetadataTest() {
+        var data = {
+            __metadata: {
+                id: "id",
+                properties: {
+                    complex: {
+                        type: "this should be overriden",
+                        properties: {
+                            nested1: {
+                                type: "types.complex.nested1",
+                                properties: {
+                                    nested2: {
+                                        type: "types.complex.nested1.nested2"
+                                    }
+                                }
+                            },
+                            c1: {
+                                type: "Edm.Int64"
+                            }
+                        }
+                    }
+                }
+            },
+            complex: {
+                __metadata: {
+                    type: "types.complex"
+                },
+                c1: "500",
+                c2: "b",
+                nested1: {
+                    nested2: {
+                    }
+                }
+            }
+        };
+
+        var expected = {
+            complex: {
+                "odata.type": "types.complex",
+                "c1@odata.type": "Edm.Int64",
+                c1: "500",
+                c2: "b",
+                nested1: {
+                    "odata.type": "types.complex.nested1",
+                    nested2: {
+                        "odata.type": "types.complex.nested1.nested2"
+                    }
+                }
+            }
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry complex property was serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeLinksDocumentTest() {
+        var tests = {
+            "Empty uri string": {
+                i: { uri: "" },
+                e: { url: "" }
+            },
+            "Null uri string": {
+                i: { uri: null },
+                e: { url: null }
+            },
+            "Undefined uri string": {
+                i: { uri: undefined },
+                e: {}
+            },
+            "Uri": {
+                i: { uri: "http://somUri/EntitySet(1)" },
+                e: { url: "http://somUri/EntitySet(1)" }
+            }
+        };
+
+        for (var name in tests) {
+            verifySerializedJsonLightData(tests[name].i, tests[name].e, name + " - Json light links documents whas serialized properly.", "http://someUri/set(3)/$links/navprop");
+        }
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithSingleKey() {
+        var model = getSampleModel();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('MyId')",
+                "edit": "http://someUri/EntityTypes('MyId')",
+                "uri": "http://someUri/EntityTypes('MyId')",
+                "self": "http://someUri/EntityTypes('MyId')"
+
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithMultipleKeys() {
+        var model = getSampleModelWithTwoKeys();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes(Id='MyId',P1=42)",
+                "edit": "http://someUri/EntityTypes(Id='MyId',P1=42)",
+                "uri": "http://someUri/EntityTypes(Id='MyId',P1=42)",
+                "self": "http://someUri/EntityTypes(Id='MyId',P1=42)"
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithNonComputedEditLink() {
+        var model = getSampleModel();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            "odata.editLink": "EntityTypes('notcomputed')",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('notcomputed')",
+                "edit": "http://someUri/EntityTypes('notcomputed')",
+                "uri": "http://someUri/EntityTypes('notcomputed')",
+                "self": "http://someUri/EntityTypes('notcomputed')"
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithSingleConcurrencyProperty() {
+        var model = getSampleModelWithOneConcurrencyProperty();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('MyId')",
+                "edit": "http://someUri/EntityTypes('MyId')",
+                "uri": "http://someUri/EntityTypes('MyId')",
+                "self": "http://someUri/EntityTypes('MyId')",
+                "etag": "W/\"'MyId'\""
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithSingleBinaryConcurrencyProperty() {
+        var model = getSampleModelWithOneBinaryConcurrencyProperty();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: "AAAAAAAAB9E="
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Binary"} },
+                "id": "http://someUri/EntityTypes('MyId')",
+                "edit": "http://someUri/EntityTypes('MyId')",
+                "uri": "http://someUri/EntityTypes('MyId')",
+                "self": "http://someUri/EntityTypes('MyId')",
+                "etag": "W/\"X'00000000000007D1'\""
+            },
+            "Id": "MyId",
+            "P1": "AAAAAAAAB9E="
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinkWithMutipleConcurrencyProperty() {
+        var model = getSampleModelWithMultipleConcurrencyProperties();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('MyId')",
+                "edit": "http://someUri/EntityTypes('MyId')",
+                "uri": "http://someUri/EntityTypes('MyId')",
+                "self": "http://someUri/EntityTypes('MyId')",
+                "etag": "W/\"'MyId',42\""
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinkWithNullConcurrencyProperty() {
+        var model = getSampleModelWithMultipleConcurrencyProperties();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "My Id'",
+            P1: null
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('My%20Id''')",
+                "edit": "http://someUri/EntityTypes('My%20Id''')",
+                "uri": "http://someUri/EntityTypes('My%20Id''')",
+                "self": "http://someUri/EntityTypes('My%20Id''')",
+                "etag": "W/\"'My%20Id''',null\""
+            },
+            "Id": "My Id'",
+            "P1": null
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+    
+    djstest.addTest(function jsonLightWithDecimalValue() {
+        var model = getSampleModelWithDecimalProperty();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "5",
+            P1: "10.5"
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": {
+                    "Id": {
+                        "type": "Edm.String"
+                    },
+                    "P1": {
+                        "type": "Edm.Decimal"
+                    },
+                },
+                "id": "http:\/\/someUri\/EntityTypes('5')",
+                "uri": "http:\/\/someUri\/EntityTypes('5')",
+                "edit": "http:\/\/someUri\/EntityTypes('5')",
+                "self": "http:\/\/someUri\/EntityTypes('5')"
+            },
+            "Id": "5",
+            "P1": "10.5"
+        };
+
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+    
+    djstest.addTest(function jsonLightNavigationPropertyAndAssociationUriShouldBeComputedTest() {
+        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#Products/@Element",
+            ID: 5,
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "ODataDemo.Product",
+                "properties": {
+                    "ID": {
+                        "type": "Edm.Int32"
+                    },
+                    "Category": {
+                        "type": "ODataDemo.Category",
+                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category",
+                    }
+                },
+                "id": "http:\/\/someUri\/Products(5)",
+                "uri": "http:\/\/someUri\/Products(5)",
+                "edit": "http:\/\/someUri\/Products(5)",
+                "self": "http:\/\/someUri\/Products(5)"
+            },
+            "ID": 5,
+            "Category": {
+                "__deferred": {
+                    "uri": "http:\/\/someUri\/Products(5)\/Category"
+                }
+            }
+        };
+
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+    
+    djstest.addTest(function jsonLightNullNavigationPropertyShouldNotBeComputedTest() {
+        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#Products/@Element",
+            ID: 5,
+            Category: null
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "ODataDemo.Product",
+                "properties": {
+                    "ID": {
+                        "type": "Edm.Int32"
+                    },
+                    "Category": {
+                        "type": "ODataDemo.Category",
+                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category",
+                         "navigationLinkUrl": "http:\/\/someUri\/Products(5)\/Category"
+                    }
+                },
+                "id": "http:\/\/someUri\/Products(5)",
+                "uri": "http:\/\/someUri\/Products(5)",
+                "edit": "http:\/\/someUri\/Products(5)",
+                "self": "http:\/\/someUri\/Products(5)"
+            },
+            "ID": 5,
+            "Category": null
+        };
+
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+    
+    djstest.addTest(function jsonLightUrisShouldBeComputedForExpandedEntities() {
+        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#Products/@Element",
+            ID: 5,
+            Category: {
+                ID: 1
+            }            
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "ODataDemo.Product",
+                "properties": {
+                    "ID": {
+                        "type": "Edm.Int32"
+                    },
+                    "Category": {
+                        "type": "ODataDemo.Category",
+                        "navigationLinkUrl": "http:\/\/someUri\/Products(5)\/Category",
+                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category"
+                    }
+                },
+                "id": "http:\/\/someUri\/Products(5)",
+                "uri": "http:\/\/someUri\/Products(5)",
+                "edit": "http:\/\/someUri\/Products(5)",
+                "self": "http:\/\/someUri\/Products(5)"
+            },
+            "ID": 5,
+            "Category": {
+                "__metadata": {
+                    "type": "ODataDemo.Category",
+                    "properties": {
+                        "ID": {
+                            "type": "Edm.Int32"
+                        },
+                        "Products": {
+                            "type": "ODataDemo.Product",
+                            "associationLinkUrl": "http:\/\/someUri\/Categories(1)\/$links\/Products"
+                        }
+                    },
+                    "id": "http:\/\/someUri\/Categories(1)",
+                    "uri": "http:\/\/someUri\/Categories(1)",
+                    "edit": "http:\/\/someUri\/Categories

<TRUNCATED>