Community Tip - Did you get called away in the middle of writing a post? Don't worry you can find your unfinished post later in the Drafts section of your profile page. X
The ThingWorx platform handles REST requests by default. This enables all services to be outsourced to REST requests based on the permissions of the user.
Nevertheless, part of the problem with allowing the default JSON result might be the organization of the response. For example, making a request to a service with an InfoTable response will return information for the DataShape used by the InfoTable and a 'rows' field containing the data of the InFoTable. This can be troublesome or a nuisance when creating efficient B2B communication or parsers for the ThingWorx response.
First, let's handle the necessary security measures and configure our permissions to create a new User and Application Key. Then, handle how to parse a JSON object in the body of the POST REST request to the ThingWorx Platform.
As an example, you will create a service that will take in a person JSON object and perform some simple calculations for the response. The simple JSON object is as follows:
{ "person": { "first_name": "John", "last_name": "Doe", "dob": "03/16/1989", "roles": [ { "role": "Manager" }, { "role": "Executive" } ] } }
Follow the steps below to set up a helper function to perform age calculations, and another to take this JSON object and simply return a response based on the age of the person:
Name | Base Type | Required |
dob | String | True |
8. Add the following JavaScript to help encode the string and return an HTML friendly string.
var result = 0; try { if(dob) { var today = new Date(); var birthDate = new Date(dob); var age = today.getFullYear() - birthDate.getFullYear(); var month = today.getMonth() - birthDate.getMonth(); if (month < 0 || (month === 0 && today.getDate() < birthDate.getDate())) { age--; } result = age; } } catch(err) { logger.error("JSONResponseThing.CalculatePersonAge(): An error occured while calculating an age - " + err.message); }
9. Click Done.
10. Click Save and you're all done with this helper service. This is a simple function to calculate a person's age with limited error handling for simplicity.
Now let's handle the JSON object coming in the request and our response.
Name | Base Type | Required |
person | JSON | True |
3. Set the Output as JSON.
4. Add the following JavaScript to help encode the string and return an HTML friendly string.
var result = {}; result.message = ""; if(!person) { result.message = "We need a person to calculate their age."; } else if(!person.dob) { result.message = "We need the person's date of birth to calculate their age."; } else { if(!person.first_name) { result.message = "The person you provided is " + me.CalculatePersonAge({dob: person.dob}) + " years old"; } else { result.message = person.first_name + " is " + me.CalculatePersonAge({dob: person.dob}) + " years old"; } }
5. Click Done and go to the Permissions tab.
6. Configure the permissions of the JSONResponseExample thing to allow access to the User you created earlier. This user will need to have runtime permissions to execute the service and must belong in an organization with visibility (ie, Everyone).
7. Click Save, and you're done.
You've just created a service that takes JSON and returns JSON. There are numerous services to work with JSON objects. There is also a service to convert your JSON object to an InfoTable, FromJSON in the InfoTableFunctions Resource. Keep in mind, you will need to set the JSON to a form that can be translated to an InfoTable. If this format is unknown, use the ToJSON service from this Resource to see an example.
If you need a quick refresher on how to run a REST request to the ThingWorx Platform, please see our REST API guide. The request to the ThingWorx Platform will be a POST method and you will need to set your Application Key in the header.
Because services are based on JavaScript (Rhino JavaScript Engine), you can create objects the same way you would anywhere else. This is a very simple concept, but it becomes more complex as you try to create data based on ThingWorx-specific entities or models.
To convert an InfoTable to a better-formed JSON object, you will need to process the InfoTable rows based on the DataShape fields. The following code will do that:
/* ...Perform code that creates an InfoTable called values... */ //Begin Processing the rows of data var result = {}; result.some_information = "some values"; result.data = []; var fields = values.dataShape.fields; for (var index = 0; index < values.getRowCount(); index++) { var entry = {}; for (var name in fields) { entry[name] = values.rows[index][name]; } result.data.push(entry); }
Looking for a quick translation to JSON? Try the ReadEntityAsJSON service of the EntityServices Resource. You can use this to respond with complex ThingWorx models or just to see the setup for the JSON object in order to translate it to something simple the way the code above handles InfoTables. For a quick example, create a User, then create a service based on the below JavaScript (set the name field of the parameter to the name of the user you create):
var params = { name: 'NameOfUserYouCreated' /* STRING */, type: 'Users' /* STRING */, key: 'SomeValue /* STRING - Encryption-Decrption Key Name is Optional*/ }; // result: JSON var result = Resources["EntityServices"].ReadEntityAsJSON(params);
There are many B2B services and applications that prefer to use XML over JSON. ThingWorx can send/receive XML via SOAP requests (POST) using the ContentLoaderFunctions Resource.
To get started, create a Thing using the below steps. You will create new services in this Thing to make SOAP requests.
NOTE: Examples of these services can be found in the XMLRequestThing entity, which is provided in the download.
You will use the PostXML service of the ContentLoaderFunctions Resource. This service takes parameters from the proxy information to handle SSL issues. All of the parameters are optional.
Perform the following steps to create your ThingWorx service to make requests.
Name | Base Type | Required |
url | String | True |
body | XML | True |
6. In the Snippets section, filter and search for PostXML.
7. Once you’ve found PostXML under the ContentLoaderFunctions section, add it to the editor. You’ll see all of the possible parameters for the request. In this example, you will set only the url and content values.
8. Update the code snippet to include the parameters. Use the below code as a reference:
try { var params = { url: url /* STRING */, content: body /* XML */, }; // result: XML var result = Resources["ContentLoaderFunctions"].PostXML(params); logger.info(" XMLRequestThing.SendXMLRequest(): Results From Calling Service - " + JSON.stringify(result)); } catch(error) { logger.error(" XMLRequestThing.SendXMLRequest(): Error Calling Service - " + error.message); }
9. Click Save and you’re done with your first SOAP request.
You can now enter your XML string as a parameter to call your new service. You can also assign your XML string directly to a variable in the service.
/*jshint multistr: true */ var body = ' \ <?xml version="1.0" encoding="UTF-8"?> \ <menu> \ <header> \ <title>A Cool Title</title> \ </header> \ <body> \ <lunch_menu> \ <food> \ <name>Belgian Waffles</name> \ <price>$5.95</price> \ <description>Two of our famous Belgian Waffles with plenty of real maple syrup</description> \ <calories>650</calories> \ </food> \ <food> \ <name>Strawberry Belgian Waffles</name> \ <price>$7.95</price> \ <description>Light Belgian waffles covered with strawberries and whipped cream</description> \ <calories>900</calories> \ </food> \ </lunch_menu> \ <breakfast_menu> \ <food> \ <name>Belgian Waffles</name> \ <price>$5.95</price> \ <description>Two of our famous Belgian Waffles with plenty of real maple syrup</description> \ <calories>650</calories> \ </food> \ <food> \ <name>Strawberry Belgian Waffles</name> \ <price>$7.95</price> \ <description>Light Belgian waffles covered with strawberries and whipped cream</description> \ <calories>900</calories> \ </food> \ <food> \ <name>Berry-Berry Belgian Waffles</name> \ <price>$8.95</price> \ <description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description> \ <calories>900</calories> \ </food> \ <food> \ <name>French Toast</name> \ <price>$4.50</price> \ <description>Thick slices made from our homemade sourdough bread</description> \ <calories>600</calories> \ </food> \ <food> \ <name>Homestyle Breakfast</name> \ <price>$6.95</price> \ <description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description> \ <calories>950</calories> \ </food> \ </breakfast_menu> \ </body> \ </menu>'; ```
Click here to view Part 3 of this guide.