First we will look at a simple REST JSON Post. The screenshot below has the service operation setup. This is the most simple web service. You will notice that:
Template other than /Document Template because we are not passing any parametersCHG_GENERIC.V1 which is a “Nonrowset-based” based messages. This is is not shown.
We plan on posting some simple JSON to this. The HTTP Signature will look like this:
POST http://localhost:8000/PSIGW/RESTListeningConnector/PSFT_CS/CHG_JSON_TEST.v1/
Authorization: Basic UFM6dHJ5aW5nLXNlZS1pZi1JLXBvc3RlZC1teS1wYXNzd29yZC1JLXNlZQ==
Content-Type: application/json
{
"firstName": "Chris",
"lastName": "Malek",
"Region": "Southern California",
"FavoriteDesert": "Pie, any kind"
}The response that comes out of this web services the following.
HTTP/1.1 200 OK
Connection: close
Date: Wed, 02 Dec 2020 04:33:21 GMT
Content-Length: 234
Content-Type: application/json; encoding="UTF-8"
Content-Encoding: gzip
Set-Cookie: JSESSIONID=6zshuetDLvmVT5G55VCUt0su3nVWAn469hsagTQOqg0zHVExziNa!-1985259815; path=/; HttpOnly,psmap=; domain=.c.peoplesoftdemo-1470578694381.internal; path=/
{
"firstName": "Chris",
"lastName": "Malek",
"Region": "Southern California",
"FavoriteDesert": "Pie, any kind",
"META": {
"OPRID": "PS",
"CURRENT_TIME": "2020-12-02 04:33:21.000000",
"TRANSACTION_ID": "81fa5f4b-3457-11eb-9b6b-e783fa52141b",
"DBNAME": "CS92U009"
}
}The handler parses the inbound root JSON object strings and echos any value back out. We also add a “META” object with some information about the run-time environment.
The entire PeopleCode handler for this web service is:
import PS_PT:Integration:IRequestHandler;
class simpleJSONPost implements PS_PT:Integration:IRequestHandler
method onRequest(&msRequest As Message) Returns Message;
end-class;
method onRequest
/+ &msRequest as Message +/
/+ Returns Message +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
Local Message &response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
Local JsonObject &responseRootJSON = CreateJsonObject();
Local string &requestPayload = &msRequest.GetContentString();
Local JsonParser &parser = CreateJsonParser();
Local boolean &bParseResult = &parser.Parse(&requestPayload);
If &bParseResult = True Then
Local integer &i;
Local JsonObject &jObj = &parser.GetRootObject();
For &i = 1 To &jObj.ChildCount
Local string &propName;
&propName = &jObj.GetPropertyNameAt(&i);
&responseRootJSON.AddProperty(&propName, &jObj.GetAsString(&propName));
End-For;
End-If;
Local JsonObject &JsonObjMETA = CreateJsonObject();
&JsonObjMETA.AddProperty("OPRID", %OperatorId);
&JsonObjMETA.AddProperty("CURRENT_TIME", %Datetime);
&JsonObjMETA.AddProperty("TRANSACTION_ID", &msRequest.TransactionId);
&JsonObjMETA.AddProperty("DBNAME", %DbName);
&responseRootJSON.AddJsonObject("META", &JsonObjMETA);
/* Push the generated XML to the response document */
If &response.SetContentString(&responseRootJSON.ToString()) Then
End-If;
Return &response;
end-method;
With this simple example you can see:
This web service has no:
A common pattern is receiving a top-level JSON array from an API search. Each element has nested objects and arrays:
[
{
"name": "Meowsy",
"species": "cat",
"foods": {
"likes": ["tuna", "catnip"],
"dislikes": ["ham", "zucchini"]
}
},
{
"name": "Barky",
"species": "dog",
"foods": {
"likes": ["bones", "carrots"],
"dislikes": ["tuna"]
}
}
]
To parse this, use GetJsonArray("") on the root object to get the top-level array, then loop through each element:
Local JsonParser &parser = CreateJsonParser();
Local string &jsonString;
/* &jsonString populated from web service or file */
Local boolean &bParseResult = &parser.Parse(&jsonString);
If &bParseResult = True Then
Local JsonObject &jObj = &parser.GetRootObject();
Local JsonArray &rootArray = &jObj.GetJsonArray("");
Local integer &i, &j;
Local JsonObject &rootObject, &foodObject;
Local JsonArray &jsonArrayFavoriteFoods;
Local string &AnimalName, &favoriteFoods;
For &i = 1 To &rootArray.Length()
&rootObject = &rootArray.GetJsonObject(&i);
&AnimalName = &rootObject.GetAsString("name");
/* Get nested object */
&foodObject = &rootObject.GetJsonObject("foods");
/* Get nested array */
&jsonArrayFavoriteFoods = &foodObject.GetJsonArray("likes");
If All(&jsonArrayFavoriteFoods) Then
&favoriteFoods = "";
For &j = 1 To &jsonArrayFavoriteFoods.Length()
If &j = 1 Then
&favoriteFoods = &jsonArrayFavoriteFoods.GetAsString(&j);
Else
&favoriteFoods = &favoriteFoods | ", " | &jsonArrayFavoriteFoods.GetAsString(&j);
End-If;
End-For;
End-If;
/* &AnimalName and &favoriteFoods now contain the parsed values */
End-For;
End-If;
To extract JSON boolean values, use GetBooleanProperty:
Local boolean &bCanBark = &rootObject.GetBooleanProperty("canBark");
If &bCanBark Then
/* This animal can bark */
End-If;
The Parse method on JsonParser will throw an exception on invalid JSON, so you need a try-catch block:
Local JsonParser &parser = CreateJsonParser();
Local string &jsonString;
/* &jsonString may contain invalid JSON */
try
If &parser.Parse(&jsonString) Then
/* Parse Success - process the JSON */
Else
/* Parse returned false */
End-If;
catch Exception &e
/* Invalid JSON - handle the error */
/* &e.ToString() will contain the position and expected tokens */
end-try;
An error message will look something like:
Invalid token [ 8 ] at position [ 45 ], Expected tokens are: [ , ]
If you don’t know the structure of the JSON ahead of time, you can iterate over properties using ChildCount, GetPropertyNameAt, IsJsonArray, and IsJsonObject:
Local JsonObject &jObj = &parser.GetRootObject();
Local integer &i;
Local string &propName, &propValue;
For &i = 1 To &jObj.ChildCount
&propName = &jObj.GetPropertyNameAt(&i);
If &jObj.IsJsonArray(&propName) Then
/* Handle array property */
Else
If &jObj.IsJsonObject(&propName) Then
/* Handle nested object */
Else
/* Simple value - get as string */
&propValue = &jObj.GetAsString(&propName);
End-If;
End-If;
End-For;
GetPropertyType method available, so you cannot easily determine if a simple value is a string, number, or boolean. You can use IsJsonArray and IsJsonObject to detect arrays and objects, but for primitive types you currently have to use GetAsString and parse the result.Chris Malek s a PeopleTools® Technical Consultant with over two decades of experience working on PeopleSoft enterprise software projects. He is available for consulting engagements.
Work with Chris