Example Using Generic (JSON) Resource Objects

Overview

The Resource interface provides a generic way to represent and interact with domain objects from various backend systems. It is designed to handle different data formats by exposing APIs for accessing properties and child objects, regardless of the backend's structure.

A common use case is working with JSON data. CRISP includes a default implementation, JacksonResource, which uses the Jackson library to parse JSON and expose its data through the Resource interface.

Mapping a Single JSON Object to a Resource

Consider the following JSON object representing product data from a backend system:

{ "SKU": "12345678901", "description": "MultiSync X123BT - 109.22 cm (43 \") , 1920 x 480, 16:4, 500 cd\/m\u00b2, 3000:1, 8 ms", "name": "CBA MultiSync X123BT", "extendedData": { "title": "CBA MultiSync X123BT", "type": "Link", "uri": "Awesome-HIC-Site\/-\/products\/12345678901", "description": "MultiSync X123BT - 109.22 cm (43 \") , 1920 x 480, 16:4, 500 cd\/m\u00b2, 3000:1, 8 ms" } }

This JSON object maps directly to a Resource instance:

  • The top-level JSON object becomes a Resource.
  • Properties such as "SKU", "description", and "name" are exposed as primitive properties. JacksonResource automatically converts these to the appropriate Java types.
  • Nested objects, such as "extendedData", are available as child Resource properties.
  • Both primitive and nested properties are accessible via Resource#getValueMap().get(String name).

To access these properties after retrieving a Resource object using ResourceServiceBroker#resolve(...), use the following approach:

ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); Resource product = resourceServiceBroker.resolve("demoProductCatalogs", "/products/sku/12345678901"); String name = (String) product.getValueMap().get("name"); String sku = (String) product.getValueMap().get("SKU"); String description = (String) product.getValueMap().get("description"); Resource extendedData = (Resource) product.getValueMap().get("extendedData"); String title = extendedData.getValueMap().get("title"); String type = extendedData.getValueMap().get("type"); String uri = extendedData.getValueMap().get("uri"); String description = extendedData.getValueMap().get("description");

In this example, the code retrieves the nested extendedData property and accesses its fields. If you want to avoid retrieving all nested descendants, especially in deeply nested structures, use Resource#getValue(String relPath) to access a property by its relative path:

ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); Resource product = resourceServiceBroker.resolve("demoProductCatalogs", "/products/sku/12345678901"); // Access the "title" property of the "extendedData" child resource directly: String title = product.getValue("extendedData/title"); // ...

Refer to the JavaDoc for the Resource interface for additional details.

Mapping a JSON Array to a Resource Collection

The following JSON array represents a collection of products:

[ { "SKU": "12345678901", "description": "MultiSync X123BT - 109.22 cm (43 \") , 1920 x 480, 16:4, 500 cd\/m\u00b2, 3000:1, 8 ms", "name": "CBA MultiSync X123BT", "extendedData": { "title": "CBA MultiSync X123BT", "type": "Link", "uri": "Awesome-HIC-Site\/-\/products\/12345678901", "description": "MultiSync X123BT - 109.22 cm (43 \") , 1920 x 480, 16:4, 500 cd\/m\u00b2, 3000:1, 8 ms" } }, { "SKU": "12345678902", "description": "PA123W, 68.58 cm (27 \") LCD, 2560 x 1440, 6ms, 1000:1, 300cd\/m2, 1.073B", "name": "CBA PA123W", "extendedData": { "title": "CBA PA123W", "type": "Link", "uri": "Awesome-HIC-Site\/-\/products\/12345678902", "description": "PA123W, 68.58 cm (27 \") LCD, 2560 x 1440, 6ms, 1000:1, 300cd\/m2, 1.073B" } }, //... ]

This JSON array is mapped to a Resource object representing a collection:

  • The root JSON array becomes a Resource where Resource#isArray() returns true.
  • Use Resource#getChildren() to iterate over the collection.

After retrieving the collection using ResourceServiceBroker#findResources(...), iterate through the resources as follows:

ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); Resource products = resourceServiceBroker.findResources("demoProductCatalogs", "/products/"); for (Resource product : products.getChildren()) { String name = (String) product.getValueMap().get("name"); String sku = (String) product.getValueMap().get("SKU"); String description = (String) product.getValueMap().get("description"); // ... }

Handling Embedded Collections in a JSON Object

Some APIs return a JSON object that contains a collection as a property, rather than as the root element. For example, the following response from the Salesforce REST API includes a "records" array within a top-level object:

{ "totalSize":27, "done":true, "records":[ { "attributes":{ "type":"Lead", "url":"/services/data/v20.0/sobjects/Lead/00Q460000020SQ7EAM" }, "FirstName":"John", "LastName":"Doe", "Status":"Working - Contacted", "Title":"Director of Vendor Relations", "Industry":"Agriculture", "State":"FL", "Country":"USA", "City":"Tallahassee", "PostalCode":"32306", "Email":"[email protected]", "Rating":"Hot" }, { "attributes":{ "type":"Lead", "url":"/services/data/v20.0/sobjects/Lead/00Q460000020SQ8EAM" }, "FirstName":"Jane", "LastName":"Doe", "Status":"Open - Not Contacted", "Title":"CFO", "Industry":null, "State":"VA", "Country":"USA", "City":null, "PostalCode":null, "Email":"[email protected]", "Rating":null }, // ... ] }

To work with this structure:

  • Map the top-level object to a Resource.
  • Retrieve the "records" property as a child Resource.
  • Iterate over the collection using getChildren() on the "records" resource.

Example:

final String SOQL_ALL_LEADS = "SELECT FirstName, LastName, Status, Title, Industry, Company, NumberOfEmployees, State, Country, City, " + "PostalCode, Email, IsDeleted, IsConverted, ConvertedAccountId, ConvertedContactId, Rating " + "FROM Lead"; ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); final Map<String, Object> pathVars = new HashMap<>(); pathVars.put("soql", SOQL_ALL_LEADS); Resource result = broker.findResources("demoSalesForce", "/query/?q={soql}", pathVars); Resource records = (Resource) result.getValueMap().get("records"); for (Resource lead : records.getChildren()) { String firstName = (String) lead.getValueMap().get("FirstName"); String lastName = (String) lead.getValueMap().get("LastName"); String email = (String) lead.getValueMap().get("Email"); // ... }

Pagination with Resource Objects

The Resource interface supports pagination for collections. Use Resource#getChildren(long offset, long limit) to retrieve a subset of items:

// ... Resource records = (Resource) result.getValueMap().get("records"); // Retrieve the first page of results with a page size of 10. for (Resource lead : records.getChildren(0, 10)) { String firstName = (String) lead.getValueMap().get("FirstName"); String lastName = (String) lead.getValueMap().get("LastName"); String email = (String) lead.getValueMap().get("Email"); // ... }

Refer to the JavaDoc for the Resource interface for further details on available methods and usage patterns.

Share Feedback
Page: /build/crisp-api/examples/example-using-generic-json-resource-objects
Section: Build
Category *