cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Learn all about the Community Ranking System, a fun gamification element of the PTC Community. X

Respond with JSON without using an InfoTable Template

deanm
1-Newbie

Respond with JSON without using an InfoTable Template

I have a number of services in my solution that are invoked via RESTful POST requests from an external application.  The services must respond with a set of values.  Each service responds with a different set of values (and as the solution matures over time, these responses could become more diverse and more numerous).

The response from the services must be in a JSON format.  I've set up the services to have the result type = JSON, but everything I try generates an error with the service.  Here is a simplified example of what may be included in the response:

{

    "siteId": <string>,        // calculated by the service

    "areaName": <string>,      // pulled from a different Thing

    "percentFailed": <number>  // calculated by the service

}

If I create this structure as a JavaScript object, I was expecting to use result = JSON.stringify(responseObj) to create a JSON object that could be used for the response.  The service crashes when converting the object to JSON just prior to finishing (i.e. the ThingWorx behind-the-scenes code can't convert it to a JSON response type).

If I use the same as above, but set the result type to STRING in the service composer window, it doesn't crash, but the response contains lots of extraneous information.  For example:

{\"dataShape\":{

  \"fieldDefinitions\":{

    \"result\":{

      \"name\":\"result\",

      \"description\":\"\",

      \"baseType\":\"STRING\",

      \"ordinal\":0,

      \"aspects\":{}}}},

      \"rows\":[{

        \"result\":\"{

          \\\"siteId\\\":\\\"Site-47\\\",

          \\\"areaName\\\":\\\"Area 51\\\",

          \\\"percentFailed\\\":\\\"23.75\\\"

        }\"

      }]

     }

   }

}

}

This is generating additional unnecessary parsing in the requesting application.  I would prefer to only have the result object returned.

I'm of the understanding that I can create an InfoTable Template for the response, temporarily instantiate a table, populate it, and the return the table.  This will generate a JSON response.  However, I'd like to avoid this approach if possible because now I'm defining the response in two places (the template and the JavaScript).  Every time a developer needs to change the response, both places need to be updated.  Additionally, the solution would end up with numerous InfoTable Templates (one per service) that will need to be maintained.  This feels like a poor design choice to me and will increase future development unnecessarily.

What I'd like is to find a solution that doesn't require an InfoTable (uses only JavaScript objects) and returns a JSON object that only contains the response values.

Any ideas are greatly appreciated!

9 REPLIES 9
maneeshr
1-Newbie
(To:deanm)

Hi Dean,

You can use inbuilt function ToJSON  which is provided under snippets  to convert output of service into JSON objetct/format.

deanm
1-Newbie
(To:maneeshr)

Maneesh,

Thanks for your response, but that method is on ThingWorx objects, such as InfoTables, but is not standard JavaScript methods, so it will only work with objects that I've also defined in ThingWorx as a Template or DataShape and then instantiated within the service code.  I don't want to have to do that dual maintenance of objects (both as a ThingWorx object and as a JavaScript data structure) because that quickly becomes a support nightmare when the customer asks for changes to a response and those changes need to be implemented in multiple places.  (Note that I am dealing with responses from a third party customer's software, as opposed to my own company's software, so I have less control over what may be needed/desired on the responses in the future.)

I would prefer to only have to define the structure once in the JavaScript service and then return that structure as a JSON object without a bunch of extraneous ThingWorx wrappers on the JSON.

maneeshr
1-Newbie
(To:deanm)

Hi Dean,

What i understand is that you want to use standard JavaScript function to convert the output of Thingworx services which may be Infotable/String/Number into  JSON object.

what you can do is , add the result of service into an array and then convert that array into JSON object using standard function JSON.stringify(array).

Thanks

deanm
1-Newbie
(To:maneeshr)

Maneesh,

That is exactly what I did.  The resulting response is the nested structure I shared in the original post.  There is a lot of extraneous ThingWorx information in the structure that the requesting application then needs to traverse to get to the actual response.  We are trying to avoid that additional traversing logic by only receiving the pertinent structure in the response.

ddas-2
1-Newbie
(To:deanm)

Hi Dean,

Did you get the solution to your problem ??

OR any work around !!!

jamesm1
5-Regular Member
(To:deanm)

Result  type JSON is the one you want. I created a simple service to test this:

result = {

    "siteId": "hello",

    "areaName": "test",

    "percentFailed": "hi"

}

with output type JSON, and I tested in postman to get the expected result:

{"percentFailed": "hi","areaName": "test","siteId": "hello"}



Note: *THIS WILL NOT SHOW UP FROM WITHIN THE COMPOSER IF YOU TEST THE SCRIRPT. THE TEST SCRIPT WINDOW IN COMPOSER WILL NOT  DISPLAY JSON OR XML BASE TYPES. YOU NEED TO TEST THIS IN POSTMAN OR SOME  OTHER TOOL*

One note: If you are  returning a JSON array, it will be wrapped in an object of the following structure

result = [1,2,3]

will return

{

     "array": [1,2,3]

}

There is a workaround for this, but it's a bit messy and depends what you are trying to do. I have a bug report open on this on Jira -- PSPT-2985.

Hi James,

Are there any updates on this extra "array" addition bug? I just experienced the same issue? I'm trying to output a "pure" JSON array without any extra stuff around it and this messes up my plans.

Can you tell me anything more about the workaround? I'm creating my array manually with "var jsonObject = [];" and adding stuff there using push(). I tested the infotable.ToJSON but that created too much extra stuff for my taste.

My TW version: 7.2.5-b56

BR,

Risto

jamesm1
5-Regular Member
(To:rvaaraniemi)

Sorry, I just saw this reply somehow. The workaround is to use PostText and passing the stringified JSON array as the content parameter, but this causes a null pointer exception that has to be caught in a try/catch block and makes the response unreadable.

BruceHulse
6-Contributor
(To:deanm)

I believe what happens with the array: [] response is that Thingworx uses JSONObject as the JSON basetype. When you return only an array, it uses the JSONArray class The two are not compatible classes, so Thingworx converts the array into an object using the name 'array' before returning the JSON.

In my experience, if you return the JSON as a string from the service, you can get [{},{},...] to return from your service. You will have to then run var xxx=JSON.parse(thestring) to use it directly in the javascript.

Top Tags