· Jun 29, 2018

Error with set parObj = {}.%FromJSON(%request.Content.ReadLineIntoStream())

I try to test our REST/JSON (POST) services,where queryparametres are in content as json and the answer in contet is also as json.

This is my testClient:

Class XXX.RESTClient Extends %RegisteredObject
ClassMethod TestXXX()
#dim tRequest As %Net.HttpRequest = ##class(%Net.HttpRequest).%New()

set tRequest.ContentType="application/json"
set jsonText=jsonStream.Read(jsonStream.Size)
set tSC=tRequest.EntityBody.Write(jsonText)

set tSC = tRequest.Post("http://server:57776/csp/XXX/testXXX")

do tRequest.HttpResponse.OutputToDevice()


in dispatchClass:

ClassMethod testXXX() As %Status
#dim tStatus As %Status = $$$OK
#dim parObj As %DynamicAbstractObject = {}
#dim dynObj As %DynamicAbstractObject = {}
set $ZT="ERROR"
goto:'..%securityCheck(.tStatus,parObj) DONE

do ..%logout(.tStatus,dynObj)
quit tStatus
set tStatus = $$$ERROR($$$CacheError,$ZE)
goto DONE

ClassMethod %securityCheck(ByRef pStatus As %Status, parObj As %DynamicAbstractObject) As %Boolean
set pStatus = $$$OK
set $ZT="ERROR"

#dim %request As %CSP.Request

if %request.ContentType'=..#CONTENTTYPE {
set pStatus=$$$ERROR($$$GeneralError,"Wrong ContentType")
goto DONE
if '$IsObject(%request.Content) {
set pStatus=$$$ERROR($$$GeneralError,"No Content")
goto DONE


do %request.Content.Rewind()
Set fstream=##class(%FileBinaryStream).%New()
do fstream.LinkToFile("content.txt")
do %request.Content.Rewind()
do fstream.CopyFrom(%request.Content)
do fstream.%Save()
AND THIS IS OK (the same):

do %request.Content.OutputToDevice()

//Content is type of %CSP.BinaryStream
do %request.Content.Rewind()
set parObj = {}.%FromJSON(%request.Content.ReadLineIntoStream()) //<== THERE I GET THE ERROR
do %request.Content.Rewind()


goto DONE 

quit $$$ISOK(pStatus)
set pStatus = $$$ERROR($$$CacheError,$ZE)
goto DONE


{"status":{"koodi":"0","selite":"Cache error: <THROW>%FromJSON+37^%Library.DynamicAbstractObject.1 *%Exception.General Premature end of data 12 Line 1 Offset 1 "}}{
        "errors":[ {
                        "error":"ERROR #5002: Cache error: <THROW>%FromJSON+37^%Library.DynamicAbstractObject.1 *%Exception.General Premature end of data 12 Line 1 Offset 1 ",
                        "params":["<THROW>%FromJSON+37^%Library.DynamicAbstractObject.1 *%Exception.General Premature end of data 12 Line 1 Offset 1 "
        "summary":"ERROR #5002: Cache error: <THROW>%FromJSON+37^%Library.DynamicAbstractObject.1 *%Exception.General Premature end of data 12 Line 1 Offset 1 "

WRC told Content is type on %CSP.Stream, not binaryStream. True, if you read %CSP.request, but this works in another application. And in errorlog Content is told to be binary stream.

+----------------- swizzled references ---------------
|          i%Content = "3@%CSP.BinaryStream"
|          r%Content = ""

What is my error? How should I change this? Some changes to testClient, not service itself?

Discussion (5)0
Log in or sign up to continue

you do .ReadLineIntoStream()  
doc says:

This reads from the stream until it find the LineTerminator and returns this as a stream. If the stream does not contain the line terminator this can potentially be the entire stream.

and your error message:  Premature end of data 12 Line 1 Offset 1     

indicates that you have hit some character interpreted as line terminator after 12 characters. (rather short for  JSON)
My guess: your JSON input is a multiline input with enough line terminators inside

As a consequence your JSON input is incomplete.

Suggested workaround

  • get length of your stream method SizeGet()
  • read full stream ignoring line terminators using method Read(ByRef len As %Integer, ByRef sc As %Status) as %CacheString

eventually, it might be necessary to remove the line terminators before  %FromJSON

OK.  for some reason the most important part of the link was truncated.

I hope it doesn't hide again.

The basic mistake happens here the definition of Request

And you are right. %CSP.Stream has no Read method because  ContentType tells you the true object . 
As in the example:

It could have been %CSP.CharacterStream as well.

Both extend over some steps %GlobalStreamAdaptor which have all the READ, WRITE, ....methods

Just reading docs and not checking inherited methods (e.g. in Studio) is mostly misleading.