Until UI5 allows for client-side data handling in OData models (coming with 1.28), JSON models are the way to go for handling client-side scenarios (offline capabilities, sorting/filtering, etc pp). Typically more than one model will be involved in the application logic, most likely at some point resulting in the need to merge data.
There's plenty of advice on the Internets on retrieving data from a JSON model, handling data changes manually, then setting the data back to the model.
They all more or less do this:
// merging arrays var oldArray = [obj1, obj2]; var newArray = [obj3, obj4]; jsonModel.setData( jQuery.merge( oldArray, newArray ) ); // adding an item jsonModel.getData().push( obj );
This works fine. But as soon as server-side data is involved, the structure of the JSON result is determined both by the service model $metadata and prepended by the "/d/results" nested object (which is OData version 2 standard by the way!).
Instead of going through the effort of manually iterating over deeply nested structures, UI5 offers the merge-Parameter on the JSON-model setData()-method: jsonModel.setData(rawODataObject, boolMerge)
In order to use that feature, the to-be-merged JSON models need to be of the same structure with corresponding array indexes.
In the example Northwind OData service above, the Employee entity with LastName "Davolio" is at d.results[0], "Fuller" at d.results[1].
If you were to add positions to them from a second OData query, the positions need to be at the desired array indexes:
This would make d.results[0] the "Sales Representative", d.results[1] the "Vice President, Sales".
Code-wise this looks schematically like this:
var sUrl = "http://services.odata.org/V2/Northwind/Northwind.svc/Employees"; // load data into client-side model var oJsonModel1 = new sap.ui.model.json.JSONModel(); // select only some fields of the Employees entity set // sync request done intentionally oJsonModel1.loadData(sUrl, {"$select": "EmployeeID,LastName,FirstName"}, false); var oJsonModel2 = new sap.ui.model.json.JSONModel(); // select different fields of the Employees entity set // sync request done intentionally oJsonModel2.loadData(sUrl, {"$select": "TitleOfCourtesy,Title"}, false); // merge the data into first JSON model oJsonModel1.setData(oJsonModel2.getData(), true);
Note the use of getData() on the to-be-merged model - in UI5 terms, it retrieves the "raw" data that subsequently can be used for the merge.
Along the same lines, a locally construced JSON model can also be merged in one retrieved from an online resource.
Again, the key is to map array indexes of the models so UI5 can merge them together correctly.
Also, the /d/results structure needs to present to merge remote and local JSON data together:
//... continued from above var oJsonModel3 = new sap.ui.model.json.JSONModel(); // note the /d/results structure - OData JSON standard! var oJson = { d : { results: [ { "LocalID" : "4711"}, { "LocalID" : "4712"}, { "LocalID" : "4713"} ] } }; oJsonModel3.setData(oJson); // merge it into first JSON model oJsonModel1.setData(oJsonModel3.getData(), true);
The resulting oJsonModel1 then looks like this:
I've put together a sample UI5 application that showcases merging both remote (aka retrieved from a URL) and remote with local JSON models.
Source-Code is over at GitHub.
Here are some screenshots:
Applying a second "remote" JSON model:
Merging both local and remote JSON models: