Author Info
Chris Malek

Chris Malek is a PeopleTools® Technical Consultant with two decades of experience working on PeopleSoft enterprise software projects. He is available for consulting engagements.

About Chris Work with Chris
Looking for pain-free PeopleSoft web services? 😀
PeopleSoft Simple Web Services (SWS)

Introducing a small but powerful PeopleSoft bolt-on that makes web services very easy. If you have a SQL statement, you can turn that into a web service in PeopleSoft in a few minutes.

Contents

JSON Encoding Examples

This section will go over how to create JSON using PeopleCode classes. There are really 2 main family of classes that can be used to create JSON.

  • JSONObject family (my preferred way)
  • JsonBuilder family

Escaping Bug

The JSON spec has some special rules around what can be in a value and how those should be escaped. The PeopleCode classes and methods do not escape these characters.

  • Backspace should be replaced with \b
  • Form feed should be replaced with \f
  • Newline should be replaced with \n
  • Carriage return should be replaced with \r
  • Tab should be replaced with \t
  • Double quote should be replaced with \"
  • Backslash should be replaced with \\

As a work around you may have to do something like this code which is NOT fully tested.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
method escapeJSONString
   /+ &instring as String +/
   /+ Returns String +/
   Local string &out;
   &out = &instring;
   /* "/" substitution  must be first */

   
   &out = Substitute(&out, Char(92), (Char(92) | Char(92)); 
   &out = Substitute(&out, Char(8), "\b");
   &out = Substitute(&out, Char(9), "\t");
   &out = Substitute(&out, Char(10), "\n");
   &out = Substitute(&out, Char(12), "\f");
   &out = Substitute(&out, Char(13), "\r");
   &out = Substitute(&out, Char(34), "\" | Char(34));
   Return &out;
end-method;

JSONObject Family Testing

Below are some examples of creating JSON with the JSONObject family of classes.

Simple JSON Output using JsonObject

Below is a simple JSON example that uses the JSONObject class. It demonstrates the following:

  • Creating simple JSON properties
  • Creating a nested object (META)
  • Output different data types:
    • Boolean
    • String
    • number
{

  "hello": "world",
  "nullTest": "",
  "longStringTest": "Here is a long string test with some <strong>HTML codes.</strong> and some {[brackets]}. ",
  "META": {

    "OPRID": "PS",
    "CURRENT_TIME": "2019-10-22 16:04:43.000000",
    "TRANSACTION_ID": "a93a7530-f4e5-11e9-8860-be56ef5f9dbf",
    "DBNAME": "CS92U009",
    "isTrueBooleanTest": true,
    "NumberValueTest": 4
  }
} 

Here is the complete handler that will produce the JSON above.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import PS_PT:Integration:IRequestHandler;

class jsonExample1 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;
   &response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
   
   Local JsonObject &rootJSON = CreateJsonObject();
   &rootJSON.AddProperty("hello", "world");
   &rootJSON.AddProperty("nullTest", "");
   
   
 
   Local string &s = "Here is a long string test with some <strong>HTML codes.</strong> and some {[brackets]}. ";
   /* bug - does not escape special characters */   
   &rootJSON.AddProperty("longStringTest", &s);
   
   Local JsonObject &JsonObjMETA = CreateJsonObject();
   
   &JsonObjMETA.AddProperty("OPRID", %OperatorId);
   &JsonObjMETA.AddProperty("CURRENT_TIME", %Datetime);
   &JsonObjMETA.AddProperty("TRANSACTION_ID", &msRequest.TransactionId);
   &JsonObjMETA.AddProperty("DBNAME", %DbName);
   &JsonObjMETA.AddProperty("isTrueBooleanTest", True);
   &JsonObjMETA.AddProperty("NumberValueTest", 4);
   
   &rootJSON.AddJsonObject("META", &JsonObjMETA);
   
   
   /* Push the generated XML to the response document */
   If &response.SetContentString(&rootJSON.ToString()) Then
      
   End-If;
   Return &response;
   
end-method;

JSONBuilder Family Testing

There is another JSON generator class called JSONBuilder where you can generate JSON. I really don’t like this class for various reasons.

  • It has a strange interface with “Start” and “End” methods that change the “builder” pointer of where you are in the JSON tree. This is just weird and I not see any other programming language use this paradigm. When you create a pointer you don’t expect it to change (at least I don’t).
  • I have tested this several times and it is very easy to completely crash the application server if you don’t call the “End” methods correct. This is just insane. If you can make a simple mistake and crash the application server then this is NOT ready for production.

JSONBuilder Example 1

Below is a JSONBuilder example that resembles the same output as the example 1 above.

{
  "hello": "world",
  "nullTest": "",
  "longStringTest": "Here is a long string test with some <strong>HTML codes.</strong> and some {[brackets]}. ",
  "META": {
    "OPRID": "PS",
    "CURRENT_TIME": "2019-10-22 16:04:43.000000",
    "TRANSACTION_ID": "a93a7530-f4e5-11e9-8860-be56ef5f9dbf",
    "DBNAME": "CS92U009",
    "isTrueBooleanTest": true,
    "NumberValueTest": 4
  }
} 

Here is the full handler.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import PS_PT:Integration:IRequestHandler;

class jsonBuilderExample1 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;
   &response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
   
   /*Nested json objects using JsonBuilder*/
   Local JsonBuilder &jb1 = CreateJsonBuilder();
   &jb1.StartObject("");
   &jb1.AddProperty("hello", "world");
   
   &jb1.AddNullProperty("nullTest");
   
   Local string &s = "Here is a long string test with some <strong>HTML codes.</strong> and some {[brackets]}. ";
   /* bug - does not escape special characters */
   &jb1.AddProperty("longStringTest", &s);
   
   &jb1.StartObject("META");
   
   &jb1.AddProperty("OPRID", %OperatorId);
   &jb1.AddProperty("CURRENT_TIME", %Datetime);
   &jb1.AddProperty("TRANSACTION_ID", &msRequest.TransactionId);
   &jb1.AddProperty("DBNAME", %DbName);
   &jb1.AddProperty("isTrueBooleanTest", True);
   &jb1.AddProperty("NumberValueTest", 4);
   
   &jb1.EndObject("META");
   &jb1.EndObject("");
   /* Push the generated XML to the response document */
   If &response.SetContentString(&jb1.ToString()) Then
      
   End-If;
   
   
   Return &response;
   
end-method;