A lot of web services return results in JSON format rather than XML. Is it possible to parse JSON in PeopleCode? Can you consume JSON web services uisng PeopleCode? Absolutely. My first attempt at parsing JSON in PeopleCode used eval
and the Rhino JavaScript scripting engine as documented in my post Scripting PeopleSoft. Because the Bean Scripting Framework's BSFEngine.eval method returns a java.lang.Object, I was left in a state of painful Java Reflection (executing each call using Java Reflection). Looking over the json.org website, I took note of the collection of Java JSON parsers. After choosing the org.json parser. I again found myself having to deal with the pain of Java Reflection (and, most definitely, I was left wishing PeopleCode had a JavaCast
function). Rather than deal with the Java reflection required to create an instance of a JSONObject or JSONArray, I chose an easier route: write a helper class to construct JSON objects. Here is the source:
package yourcompany.json;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class ParseHelper {
private ParseHelper() {
}
public static JSONObject objectFromString(String json) throws JSONException {
return new JSONObject(json);
}
public static JSONArray arrayFromString(String json) throws JSONException {
return new JSONArray(json);
}
}
If my JSON looks like
{
"EMPLID": "E1234",
"NAME": "Marion,Jim",
"DIRECTS": [
{
"EMPLID": "E5678",
"NAME": "Doe,John"
},
{
"EMPLID": "E2468",
"NAME": "Doe,Jane"
}
]
}
Then I can enumerate the directs array using PeopleCode like:
Local string &json_data = "my JSON string...";
REM ** use static helper class to avoid ugly Java reflection;
Local JavaObject &json = GetJavaClass("yourcompany.json.ParseHelper").objectFromString(&json_data);
Local JavaObject &directsArr = &json.getJSONArray("DIRECTS");
Local number &length = &directsArr.length();
Local number &directsIdx = 0;
For &directsIdx = 0 To &length - 1
Local JavaObject &direct = &directsArr.getJSONObject(&directsIdx);
&logger.debug("DIRECTS [" | &directsIdx | "] " | &direct.get("NAME").toString());
End-For;
14 comments:
Hi Jim,
Gr8 :) blog on JSON. I was wanting to see something like that for some time...Coz people were really talking about JSON rather than XML...
Thank you for your inputs.
All the best
Thank you
Awesome post Jim!
I was wondering if there is a way to read the JSON that is being returned by a third-party webservice.
In the above example, you are building the string. I was able to use this test code to test that I am able to read a JSON that I created in Peoplecode.
But what would be the best way to read the JSON (using Peoplecode) that the third-party is returning when we make a call to them.
We are on Tools 8.52
Thanks much!!
@Abhay, it is the same. Are you using %IntBroker.ConnectorRequestUrl? It returns a string. You would just call objectFromString passing in the result of ConnectorRequestUrl.
My PeopleTools Tips and Techniques book has examples of using the JSON.simple parser instead of the org.json parser. I found JSON.simple to be a little easier to use from PeopleCode.
The Documents module in PeopleTools 8.53 supports JSON parsing, so in 8.53 you do not need a special library to make this happen.
Thank you once again, @Jim!! I was not using ConnectorRequestURL, but now am. :)
Works like a charm! Will definitely check out your book..
Jim:
This has been extremely helpful. I got one of our Java guys to create a class very similar to the code example that you showed. I put his jar file (as well as json-jena-1.0.jar that he referred to in his code) in /opt/psoft/ptools/usr/classes, and it's working great for calling a web service and parsing out the records that I want.
One thing that took me a while to figure out--in one case I needed to go multiple levels into the JSON tree. So, using this snippet of JSON:
"task": {
"id": 5,
"type": "TASK",
"completionUrl": null,
"expectedCompletion": "2013-11-01T00:00:00-0600",
"studentReadFlag": false,
"createdDateTime": "2013-10-29T12:53:48-0600",
"creator": {
"personId": "328263412",
"name": "Goodman, Tayler"
},
"student": {
"personId": "112210202",
"name": "Ithaca, Johhny Appleseed"
in order to get the student name, I had to declare a JavaObject for both the task and the student, before I could get the student's name, as in the following:
Local JavaObject &task = &result.getJSONObject("task"); /* get the task branch */
Local JavaObject &student = &task.getJSONObject("student");
&strStudentName = &student.get("name").toString();
Thanks again!
@Frank, thank you for sharing.
Some of the custom Java methods seems to be missing . getJSONArray for example. Further, I also found a tutorial that talks about customizing JSON.simple, may be useful for the community.
Read / Parse JSON in PeopleCode, with Changes to JSON.Simple
Hi Jim,
We are using tools 8.53 and trying to parse the json returned from the google search api
http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=
I am using document to handle the json response but it runs to an infinite loop. What may be missing? is it a problem with document structure?
Thank you
@Mathumitha, first, congratulations on creating a Document structure that matches someone else's JSON. I assume you are iterating over your collections and it is in the iterating that you experience the infinite loop?
Jim, this is amazing help! Thank you so much for your contribution to the PeopleSoft space. My only suggest is do you have a link that can help people with the java setup that is required along with this development? I was lucky like @Frank to have someone help me with that aspect but not sure everyone has that benefit.
Hi Jim,
You are so helpful! I'm wondering if you have tested with peopletools 8.59 now.
I am not sure how to de-serialize the JSON data I have in a REST json Response.
Thanks!
As of 8.57, this approach still works, but isn't necessary. We now have a built-in PeopleCode JsonParser. I recommend using the native PeopleCode version going forward. It is much faster.
We are on 8.58 and planning to consume JSON string using API. Can someone please help me how to consume JSON using API. This will be invoked through Single -Signon PeopleCode.
@Parth, the modern approach would be to use:
Local JsonParser &p = CreateJsonParser();
Local JsonObject &j;
&p.parse(&jsonStr);
&j = &p.GetJsonObject();
This is assuming your JSON is in a string. If your JSON is in a Document-based message, then the code would be different.
Post a Comment