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:

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

    1. Volker Buzek Post author

      I would expect them to be merged anyway, but not in the desired way – you’ll most likely end up with duplicate entries. The Employee ID will not be taken into account, the important attribute for merging is the array keys of both arrays – read: indexed array, not associative array

      (0) 

Leave a Reply