Contents

JSON Decoding Examples

Simple REST JSON Post - Example 1

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:

  • There is no Template other than /
  • There is no Document Template because we are not passing any parameters
  • The Request and Response Message objects are both CHG_GENERIC.V1 which is a “Nonrowset-based” based messages. This is is not shown.
Service Operation Setup

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:

  • How to get the raw unparsed JSON string from the request message
  • Parse a simple JSON object
  • Return back JSON data

This web service has no:

  • Error Handling
  • JSON detection of different data types
  • Any real practical use

Parsing a JSON Array with Nested Objects

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;

Extracting Boolean Values

To extract JSON boolean values, use GetBooleanProperty:

Local boolean &bCanBark = &rootObject.GetBooleanProperty("canBark");

If &bCanBark Then
   /* This animal can bark */
End-If;

Handling Invalid JSON

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: [ , ]

Dynamic JSON Parsing

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;

Author Info
Chris Malek

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