Question
Rick Prichett · Mar 6, 2021

Receiving ERROR #9406 on a string

 

My response definition is below.  I keep getting ERROR #9406: Unexpected format for value of field, physicianFirstName, using class base mapping. Any ideas would be helpful.

response: 

Response is [{"physicianFirstName":"STEVENSON","physicianLastName":"HOWARD","physicianMiddleNameInitial":"W","physicianSpecialty":"null","physicianNPI":"null","physicianMPIN":"null","physicianTaxID":"null","physicianADRId":"null","physicianAddressLine1":"null","physicianCity":"null","physicianState":"null","physicianZip":"null","physicianZipPlus4":"null","physicianPhone":"null","facilityNPI":"null","facilityAddressLine1":"\"\"","facilityCity":"\"\"","facilityState":"\"\"","facilityZip":"\"\"","error":"Invalid NPI. Requested NPI should contain 10 numeric digits","cdsm_Physician_Issue_ID":"null"}]
 

response defintion 
Class 
CDSM.ProviderAPI.Response Extends (%Persistent, %XML.Adaptor, %JSON.Adaptor) [ Language = objectscript ]response definition :

{
 

Property physicianFirstName As %String;

Property physicianLastName As %String;

Property physicianMiddleNameInitial As %String;

Property physicianSpecialty As %String;

Property physicianNPI As %String;

Property physicianMPIN As %String;

Property physicianTaxID As %String;

Property physicianADRId As %String;

Property physicianAddressLine1 As %String;

Property physicianCity As %String;

Property physicianState As %String;

Property physicianZip As %String;

Property physicianZipPlus4 As %String;

Property physicianPhone As %String;

Property facilityNPI As %String;

Property facilityAddressLine1 As %String;

Property facilityCity As %String;

Property facilityState As %String;

Property facilityZip As %String;

Property error As %String(MAXLEN = 200);

Property "cdsm_Physician_Issue_ID" As %String;

}

Product version:
IRIS 2020.2
00
1 0 16 121
Log in or sign up to continue

Replies

Get 0th array element from your array:

Class test.Provider Extends (%RegisteredObject, %JSON.Adaptor)
{

Property physicianFirstName As %String;

Property physicianLastName As %String;

Property physicianMiddleNameInitial As %String;

Property physicianSpecialty As %String;

Property physicianNPI As %String;

Property physicianMPIN As %String;

Property physicianTaxID As %String;

Property physicianADRId As %String;

Property physicianAddressLine1 As %String;

Property physicianCity As %String;

Property physicianState As %String;

Property physicianZip As %String;

Property physicianZipPlus4 As %String;

Property physicianPhone As %String;

Property facilityNPI As %String;

Property facilityAddressLine1 As %String;

Property facilityCity As %String;

Property facilityState As %String;

Property facilityZip As %String;

Property error As %String(MAXLEN = 200);

Property "cdsm_Physician_Issue_ID" As %String;

ClassMethod GetJSON() [ CodeMode = expression ]
{
[
    {
        "physicianFirstName": "STEVENSON",
        "physicianLastName": "HOWARD",
        "physicianMiddleNameInitial": "W",
        "physicianSpecialty": "null",
        "physicianNPI": "null",
        "physicianMPIN": "null",
        "physicianTaxID": "null",
        "physicianADRId": "null",
        "physicianAddressLine1": "null",
        "physicianCity": "null",
        "physicianState": "null",
        "physicianZip": "null",
        "physicianZipPlus4": "null",
        "physicianPhone": "null",
        "facilityNPI": "null",
        "facilityAddressLine1": "\"\"",
        "facilityCity": "\"\"",
        "facilityState": "\"\"",
        "facilityZip": "\"\"",
        "error": "Invalid NPI. Requested NPI should contain 10 numeric digits",
        "cdsm_Physician_Issue_ID": "null"
    }
]
}

/// do ##class(test.Provider).Test()
ClassMethod Test()
{
    set json = ..GetJSON()
    
    set obj = ..%New()
    set sc = obj.%JSONImport(json.%Get(0))
    
    zw sc,obj
}

}

I would also recommend rewriting this property:

Property "cdsm_Physician_Issue_ID" As %String;

like this:

Property physicianIssueID As %String(%JSONFIELDNAME = "cdsm_Physician_Issue_ID");

This way JSON would still be imported, but you would be able to refer to property name without double quotes.

It looks like my response is not a true JSON response (encapsulated in {}) but, is returned as a JSON array like the example.   is there any way to read in my response so that I can access the variables?

[ { "physicianFirstName": "STEVENSON", "physicianLastName": "HOWARD", "physicianMiddleNameInitial": "W", "physicianSpecialty": "null", "physicianNPI": "null", "physicianMPIN": "null", "physicianTaxID": "null", "physicianADRId": "null", "physicianAddressLine1": "null", "physicianCity": "null", "physicianState": "null", "physicianZip": "null", "physicianZipPlus4": "null", "physicianPhone": "null", "facilityNPI": "null", "facilityAddressLine1": "\"\"", "facilityCity": "\"\"", "facilityState": "\"\"", "facilityZip": "\"\"", "error": "Invalid NPI. Requested NPI should contain 10 numeric digits", "cdsm_Physician_Issue_ID": "null" } ]

Yes, check my other reply, I get the zeroth element from the JSON array with %Get(0).

Also both [] and {} are valid JSON.

How would I modify the code below to return the  response so that it  can be accessed as an array later in the code?

/// REST EISL Provider API Business Operation
Class CDSM.ProviderAPI.EISLProviderAPIOperation Extends EnsLib.REST.Operation [ Language = objectscript ]
{ Parameter INVOCATION = "Queue"; Method getProviderInfo(pRequest As CDSM.ProviderAPI.Request, Output pResponse As CDSM.ProviderAPI.ProviderInfo) As %Status
{ Try { Set tSC = $$$OK
//Build the API request
Set tHttpRequest = ##class(%Net.HttpRequest).%New()
Set tHttpRequest.ContentType = "application/json"
Set tSC = pRequest.%JSONExportToStream(.tJSONRequest) Quit:$$$ISERR(tSC)
Set tSC = tHttpRequest.EntityBody.CopyFrom(tJSONRequest) Quit:$$$ISERR(tSC)
Set tSC = tHttpRequest.EntityBody.Rewind() //Build the Response
#Dim tHttpResponse As %Net.HttpResponse
Set tSC = ..Adapter.SendFormDataArray(.tHttpResponse,"POST",tHttpRequest) If $$$ISERR(tSC) && $IsObject(tHttpResponse) && (tHttpResponse.Data.Size) {
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$StatusDisplayString(tSC)_":"_tHttpResponse.Data.Read())
//Quit:$$$ISERR(tSC)
} If $IsObject(tHttpResponse) {
$$$LOGINFO("Response is "_tHttpResponse.Data.Read())
Set tSC = tHttpResponse.Data.Rewind() Quit:$$$ISERR(tSC)
// Copy the contents of HttpResponse into pResponse
// Navigate pResponse and grab the things we want to store into SQL
// SQL Insert
Set pResponse=##class(CDSM.ProviderAPI.Response).%New()
Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read()) Quit:$$$ISERR(tSC) }
catch {
Set tSC = $$$SystemError
}
Quit tSC
} // below is not auto generated programmer must put XData MessageMap
{
<MapItems>
  <MapItem MessageType="CDSM.ProviderAPI.Request">
    <Method>getProviderInfo</Method>
  </MapItem>
</MapItems>
} }
 

If you're sure that there's only one object in response, replace:

Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

with:

Set tSC = pResponse.%JSONImport({}.%FromJSON(tHttpResponse.Data).%Get(0)) 

If you want to parse an entire array, you'll need another class:

Class CDSM.ProviderAPI.Responses Extends (%Persistent, %JSON.Adaptor) {

Property Responses As List Of CDSM.ProviderAPI.ProviderInfo;

}

And in this case replace this code:

Set pResponse=##class(CDSM.ProviderAPI.Response).%New()
Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

With:

Set pResponse=##class(CDSM.ProviderAPI.Responses).%New()
Set tSC = pResponse.%JSONImport(tHttpResponse.Data)

and update the method signature too.

I verified with the group sending the reply there will only be one.  I would define a class but the reply does not have a tag to be identified in the reply (example above). How would I build a class in that case or would it be easier to Output pResponse As CDSM.ProviderAPI.ProviderInfo in the method as something else.  This would also Set pResponse=##class(CDSM.ProviderAPI.Response).%New()  need changed I do believe as well.

If the  [ ] brackets were stripped off would the class definition work?  if so how would I strip them on in the class?

If you're sure that there's only one object in response array, replace:

Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

with:

Set tSC = pResponse.%JSONImport({}.%FromJSON(tHttpResponse.Data).%Get(0)) 

It would parse your JSON stream into a dynamic JSON array (via {}.%FromJSON(tHttpResponse.Data)), get zeroth element from it (via %Get(0)), and pass it for JSON import (via pResponse.%JSONImport).

This this error when I replace the old code with the new line.  It looks to me as though all are matched.  Is there a bug?

Your code has a bracket at the end:

You might have erased it accidentally?

It was on another line below.  The error is still there but it looks like all brackets are matched.

/// REST EISL Provider API Business Operation
Class CDSM.ProviderAPI.EISLProviderAPIOperation Extends EnsLib.REST.Operation [ Language = objectscript ]
{ Parameter INVOCATION = "Queue"; Method getProviderInfo(pRequest As CDSM.ProviderAPI.Request, Output pResponse As CDSM.ProviderAPI.ProviderInfo) As %Status
{ Try { Set tSC = $$$OK
//Build the API request
Set tHttpRequest = ##class(%Net.HttpRequest).%New()
Set tHttpRequest.ContentType = "application/json"
Set tSC = pRequest.%JSONExportToStream(.tJSONRequest) Quit:$$$ISERR(tSC)
Set tSC = tHttpRequest.EntityBody.CopyFrom(tJSONRequest) Quit:$$$ISERR(tSC)
Set tSC = tHttpRequest.EntityBody.Rewind() //Build the Response
#Dim tHttpResponse As %Net.HttpResponse
Set tSC = ..Adapter.SendFormDataArray(.tHttpResponse,"POST",tHttpRequest) If $$$ISERR(tSC) && $IsObject(tHttpResponse) && (tHttpResponse.Data.Size) {
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$StatusDisplayString(tSC)_":"_tHttpResponse.Data.Read())
//Quit:$$$ISERR(tSC)
} If $IsObject(tHttpResponse) {
$$$LOGINFO("Response is "_tHttpResponse.Data.Read())
Set tSC = tHttpResponse.Data.Rewind() Quit:$$$ISERR(tSC)
// Copy the contents of HttpResponse into pResponse
// Navigate pResponse and grab the things we want to store into SQL
// SQL Insert
Set pResponse=##class(CDSM.ProviderAPI.Response).%New()
Set tSC = pResponse.%JSONImport({}.%FromJSON(tHttpResponse.Data).%Get(0))}
catch {
Set tSC = $$$SystemError
}
Quit tSC
} // below is not auto generated programmer must put XData MessageMap
{
<MapItems>
  <MapItem MessageType="CDSM.ProviderAPI.Request">
    <Method>getProviderInfo</Method>
  </MapItem>
</MapItems>
} }
 

You probably have a mismatched brackets somewhere.

You can also try

[].%FromJSON

instead of

{}.%FromJSON

The [ ] seems to let it compile.  How do I access the array?  For example how would I get physicianFirstName from the array? Before I have been able to do something like this.  Set pLOB = pResponse.memberPolicies.GetAt(1).insuranceInfo.lineOfBusiness

I now keep getting this

 

An error was received : ERROR <Ens>ErrException: <UNDEFINED>zgetProviderInfo+24^CDSM.ProviderAPI.EISLProviderAPIOperation.1 *tsc -- logged as '-' number - @' Set pphysicianFirstName =tsc.GetAt(0).physicianFirstName'

I tried tsc.GetAt(1).physicianFirstName'  as well.

pResponse.physicianFirstName

Thanks for all your help! Our group is transitioning to Iris from Mirth and Object script is a very different beast.