Technote: Limitations of NotesHTTPRequest and NotesJSONNavigator with future considerations

If you are already using the NotesHTTPRequest and / or NotesJSONNavigator classes in your code and you are experiencing one of the following issues, here is an important technote for you.

  • SPR# DCONB8VMAV – NotesJSONNavigator is unable to parse JSON content > 64k
  • SPR# ASHEB95LFR – Unable to parse JSON string: Missing a name for object member, offset 1
  • SPR# DCONB8F6JV – bad character conversion happening in NotesHTTPRequest response
  • SPR# ASHEB95LFR – NotesJSONNavigator unable to navigate a string which contains new lines and carriage returns
  • SPR# DCONBB2KNR – NotesJSONNavigator experiencing severe issues when parsing packages with empty string values
  • SPR# JCORBB2KWU – Unable to Post > 64K String in NotesHTTPRequest
  • SPR# DCONBB44T4 – Creating a NotesJSONNavigator from nulled response causes crash

https://www-01.ibm.com/support/docview.wss?uid=ibm10875724


NotesJsonNavigator.getElementByPointer example

Sample code:

Const white = |{"color": "white", "category": "value","code": {"rgba": [0,0,0,1],"hex": "#FFF"}}|

Public Sub testJsonNavGetElementByPointer()
	Dim session As New NotesSession
	Dim jsnav As NotesJSONNavigator 
	Dim el As NOTESJSONELEMENT
	
	Set jsnav = session.CreateJSONNavigator(removeCRLF(white)) 
	
	'// returns "value"
	Set el = jsnav.Getelementbypointer("/category")
	MsgBox "category: " + el.Value
	
	'// returns "#FFF"
	Set el = jsnav.Getelementbypointer("/code/hex")
	MsgBox "hex: " + el.Value
	
	'// returns the 4th element in the rgba array  "1"
	Set el = jsnav.Getelementbypointer("/code/rgba/3")
	MsgBox "code/rgba/3: " + el.Value
End Sub

General information about JSON pointer: https://tools.ietf.org/html/rfc6901


NotesJsonNavigator.getNthElement does not obey boundries

I stumbled upon an issue with NotesJsonNavigator getNthElement(index) method.

It looks like there is no boundry check, which leads to some inconsitent behaviour and unpredictable results.

Here is the code that I used in my test.

%REM
	Sub testJsonNavGetNthElement
%END REM
Public Sub testJsonNavGetNthElement
	Dim s As New NotesSession 
	Dim jsnav As NotesJSONNavigator
	Dim el As NotesJSONElement
	
	Set jsnav = s.CreateJSONNavigator(|{ "element1" : "value 1", "element2" : "value 2", "element3 ": "value 3" }|)	
	
	Set el = jsnav.GetNthElement(0)
	Stop
	Set el = jsnav.GetNthElement(1)
	Stop
	Set el = jsnav.GetNthElement(2)
	Stop
	Set el = jsnav.GetNthElement(3)
	Stop
	Set el = jsnav.GetNthElement(1000)
	Stop
End Sub

The issue occurs with index < 1 and > upper bound of the array.

Index 0 AND index 1 both return the same value; “value 1“.
Index 1000 returns NULL or nothing.

This is not the expected behaviour. At least I would expect some “out of bounds” error.
Also, it is not clear for me what the base for the index is. Do we start counting at 0 or do we start with 1 ?

According to the documentation, the index is 1-based.


NotesJsonNavigator, NotesJsonElement, NotesJsonArray, NotesJsonObject example

NotesJsonNavigator, NotesJsonElement, NotesJsonArray, NotesJsonObject are new classes in Domino Designer as of Notes V10.0.1. They are not yet documented in the Domino Designer Help, but you can find online documentation following the above links.

The documentation also contains some basic samples.

In this article, I will demonstrate how to use the classes beyond the basic examples.
I’ll also show, how you can use the new NotesHttpRequest class to connect to a server and read and parse view data as JSON.

The first thing you need to know is that the NotesJsonNavigator class does not like CRLF.
When you try to create a new NotesJsonNavigator from the following JSON data

Const colors = |{
  "colors": [
    {
      "color": "black",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [255,255,255,1],
        "hex": "#000"
      }
    },
    {
      "color": "white",
      "category": "value",
      "code": {
        "rgba": [0,0,0,1],
        "hex": "#FFF"
      }
    },
    {
      "color": "red",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [255,0,0,1],
        "hex": "#FF0"
      }
    },
    {
      "color": "blue",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [0,0,255,1],
        "hex": "#00F"
      }
    },
    {
      "color": "yellow",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [255,255,0,1],
        "hex": "#FF0"
      }
    },
    {
      "color": "green",
      "category": "hue",
      "type": "secondary",
      "code": {
        "rgba": [0,255,0,1],
        "hex": "#0F0"
      }
    }
  ]
}|

you will get an error.

You can remove all CRLF from the data using this helper function.

Public Function removeCRLF(json As String) As String
	removeCRLF = Replace(Replace(json, Chr(13), ""),Chr(10),"")
End Function

Let us create the NotesJsonNavigator from NotesSession first.

Dim session As New NotesSession 
Dim jsnav As NotesJSONNavigator 
	
Dim json As String
json = removeCRLF(colors)
Set jsnav = session.CreateJSONNavigator(json)

Now we can count how many different colors we would find in our JSON object

Dim el As NOTESJSONELEMENT
Dim arr As NOTESJSONARRAY
	
Set el = jsnav.GetFirstElement()

Set arr = el.value
	
MsgBox "Elements count: " + CStr(arr.size)

And finally, we want to get the value for the second color in the JSON object.

Although there is a GetNthElement (index) method, this method seems to be buggy or not yet fully implemented. GetNthElement(index) will always return the first element from the JSON object.

So we will use GetFirstElement and GetNextElement to navigate thru the object.

'Set el = arr.Getnthelement(2)
Set el = arr.GetFirstElement()
Set el = arr.GetNextElement()

Dim obj As NOTESJSONOBJECT
Set obj = el.Value
Set el = obj.Getelementbyname("color")
	 
MsgBox "color: " + CStr(el.Value)

The next sample creates a NotesHttpRequest and gets JSON from a view in a Notes application. Then we retrieve the UNID and NoteId from the data returned using the new NotesJson… classes.

%REM
	Library 10010.http
	Created Jan 1, 2019 by Ulrich Krause/singultus
	Description: Comments for Library
%END REM
Option Public
Option Declare

Public Sub httpGet
	Dim Session As New NotesSession        
	Dim ret As String
	Dim URL As String

	Dim user As String
	Dim password As String
	
	Dim httpReq As NotesHTTPRequest
	Set httpReq = session.CreateHttpRequest()
	
	httpReq.Preferstrings = True
	
	user = "firstname.lastname@tld.de"
	password = "pAssw0rd"
	
	URL = "https://yourserver/names.nsf/($certifiers)?readviewentries&outputformat=JSON"

	Call httpReq.Setheaderfield("Authorization", "Basic " + EncodeBase64 (user + ":" + password))

	Dim json As string
	json = httpReq.Get(URL)

	Dim jsnav As NotesJSONNavigator 
	Set jsnav = session.CreateJSONNavigator(removeCRLF(json))

	Dim el As NOTESJSONELEMENT
	Dim arr As NOTESJSONARRAY
	Dim obj As NOTESJSONOBJECT

	Set el = jsnav.GetElementByName("viewentry")

	Set arr = el.value
	Set el = arr.GetFirstElement()
	Set el = arr.GetNextElement()
	Set obj = el.Value
	Set el = obj.Getelementbyname("@unid")

	MsgBox "unid: " + CStr(el.Value)
	Set el = obj.Getelementbyname("@noteid")

	MsgBox "noteid: " + CStr(el.Value)

End Sub

Private Function removeCRLF(json As String) As String
	removeCRLF = Replace(Replace(json, Chr(13), ""),Chr(10),"")
End Function

Private Function EncodeBase64 (StrIn As String) As String
	Dim session As New NotesSession
	Dim stream As NotesStream
	Dim db As NotesDatabase
	Dim doc As NotesDocument
	Dim body As NotesMIMEEntity
	
	Set stream = session.CreateStream
	Call stream.WriteText (StrIn)
	
	Set db = session.CurrentDatabase
	Set doc = db.CreateDocument
	Set body  = doc.CreateMIMEEntity
	
	Call body.SetContentFromText (stream, "", ENC_NONE)
	Call body.EncodeContent (ENC_BASE64)
	
	EncodeBase64 = body.ContentAsText
	
	Call stream.Close
	Set doc = Nothing
End Function