How to handle null array in output contract?

What is the proper way to handle an Null of an array in an output contract, I thought this could possibly be done with Velocity scripting #If but everything I tried hasn't worked and I am just guessing at the correct syntax.

The output contract has an array which can contain objects, but the array can contain nothing and be Null.
When it is null I we get the following error:

{
  "message": "JSON failed output schema validation for the following reasons: Schema: # @/properties/OrderStatuses/items.  Error location: /OrderStatuses/0.  instance type (null) does not match any allowed primitive type (allowed: [\"object\"])",
  "code": "invalid.schema",
  "status": 400,
  "messageParams": {},
  "contextId": "26292999-c265-485e-bbb2-81cbda878d2f",
  "details": [
    {
      "errorCode": "ACTION.PROCESSING"
    }
  ],
  "errors": []
}

I have tried this in the configuration :

 "successTemplate": "{ #if( $rawResult.CUST_CD) \"CUST_CD\": ${rawResult.CUST_CD}, #end #if( $rawResult.CUST_EDP_ID) \"CUST_EDP_ID\": ${rawResult.CUST_EDP_ID}, #end #if( $rawResult.LNAME) \"LNAME\": ${rawResult.LNAME}, #end #if( $rawResult.FNAME) \"FNAME\": ${rawResult.FNAME}, #end #if( $rawResult.STREET) \"STREET\": ${rawResult.STREET}, #end #if( $rawResult.CITY) \"CITY\": ${rawResult.CITY}, #end #if( $rawResult.STATE) \"STATE\": ${rawResult.STATE}, #end #if( $rawResult.ZIP) \"ZIP\": ${rawResult.ZIP}, #end #if( $rawResult.DAY_PHONE) \"DAY_PHONE\": ${rawResult.DAY_PHONE}, #end #if( $rawResult.NIGHT_PHONE) \"NIGHT_PHONE\": ${rawResult.NIGHT_PHONE}, #end #if( $rawResult.FAX_PHONE) \"FAX_PHONE\": ${rawResult.FAX_PHONE}, #end #if( $rawResult.Memberstatus) \"Memberstatus\": ${rawResult.Memberstatus}, #end #if( $rawResult.Account_Type) \"Account_Type\": ${rawResult.Account_Type}, #end #if( $rawResult.Rep_ID) \"Rep_ID\": ${rawResult.Rep_ID}, #end #if( $rawResult.CUST_EDP) \"CUST_EDP\": ${rawResult.CUST_EDP}, #end #if( $rawResult.CUST_NO) \"CUST_NO\": ${rawResult.CUST_NO}, #end #if( $rawResult.OrderStatuses) \"OrderStatuses\": ${rawResult.OrderStatuses}, #end }"

And I get this error:

{
  "message": "Transform failed to process result using 'successTemplate' template due to error:'Object 'java.lang.String' does not contain property 'CUST_CD' at successTemplate[line 1, column 19]'\n Template:'{ #if( $rawResult.CUST_CD) \"CUST_CD\": ${rawResult.CUST_CD}, #end #if( $rawResult.CUST_EDP_ID) \"CUST_EDP_ID\": ${rawResult.CUST_EDP_ID}, #end #if( $rawResult.LNAME) \"LNAME\": ${rawResult.LNAME}, #end #if( $rawResult.FNAME) \"FNAME\": ${rawResult.FNAME}, #end #if( $rawResult.STREET) \"STREET\": ${rawResult.STREET}, #end #if( $rawResult.CITY) \"CITY\": ${rawResult.CITY}, #end #if( $rawResult.STATE) \"STATE\": ${rawResult.STATE}, #end #if( $rawResult.ZIP) \"ZIP\": ${rawResult.ZIP}, #end #if( $rawResult.DAY_PHONE) \"DAY_PHONE\": ${rawResult.DAY_PHONE}, #end #if( $rawResult.NIGHT_PHONE) \"NIGHT_PHONE\": ${rawResult.NIGHT_PHONE}, #end #if( $rawResult.FAX_PHONE) \"FAX_PHONE\": ${rawResult.FAX_PHONE}, #end #if( $rawResult.Memberstatus) \"Memberstatus\": ${rawResult.Memberstatus}, #end #if( $rawResult.Account_Type) \"Account_Type\": ${rawResult.Account_Type}, #end #if( $rawResult.Rep_ID) \"Rep_ID\": ${rawResult.Rep_ID}, #end #if( $rawResult.CUST_EDP) \"CUST_EDP\": ${rawResult.CUST_EDP}, #end #if( $rawResult.CUST_NO) \"CUST_NO\": ${rawResult.CUST_NO}, #end #if( $rawResult.OrderStatuses) \"OrderStatuses\": ${rawResult.OrderStatuses}, #end }'.",
  "code": "bad.request",
  "status": 400,
  "messageParams": {},
  "contextId": "06f55868-0dfb-4477-b0b5-46586fbed581",
  "details": [
    {
      "errorCode": "ACTION.PROCESSING"
    }
  ],
  "errors": []
}

I have also tried this configuration, I get no errors but no values for anything which is also not correct.

"successTemplate": "{ #if($CUST_CD) \"CUST_CD\": ${CUST_CD}, #end #if( $CUST_EDP_ID) \"CUST_EDP_ID\": ${CUST_EDP_ID}, #end #if($LNAME) \"LNAME\": ${LNAME}, #end #if($FNAME) \"FNAME\": ${FNAME}, #end #if($STREET) \"STREET\": ${STREET}, #end #if( $CITY) \"CITY\": ${CITY}, #end #if( $STATE) \"STATE\": ${STATE}, #end #if( $ZIP) \"ZIP\": ${ZIP}, #end #if( $DAY_PHONE) \"DAY_PHONE\": ${DAY_PHONE}, #end #if( $NIGHT_PHONE) \"NIGHT_PHONE\": ${NIGHT_PHONE}, #end #if( $FAX_PHONE) \"FAX_PHONE\": ${FAX_PHONE}, #end #if( $Memberstatus) \"Memberstatus\": ${Memberstatus}, #end #if( $Account_Type) \"Account_Type\": ${Account_Type}, #end #if( $Rep_ID) \"Rep_ID\": ${Rep_ID}, #end #if( $CUST_EDP) \"CUST_EDP\": ${CUST_EDP}, #end #if( $CUST_NO) \"CUST_NO\": ${CUST_NO}, #end #if( $OrderStatuses) \"OrderStatuses\": ${OrderStatuses}, #end }"

Here is the Schema:

{
  "title": "Output",
  "type": "object",
  "properties": {
    "CUST_CD": {
      "type": "string"
    },
    "CUST_EDP_ID": {
      "type": "number"
    },
    "LNAME": {
      "type": "string"
    },
    "FNAME": {
      "type": "string"
    },
    "STREET": {
      "type": "string"
    },
    "CITY": {
      "type": "string"
    },
    "STATE": {
      "type": "string"
    },
    "ZIP": {
      "type": "string"
    },
    "DAY_PHONE": {
      "type": "string"
    },
    "NIGHT_PHONE": {
      "type": "string"
    },
    "Memberstatus": {
      "type": "string"
    },
    "Account_Type": {
      "type": "string"
    },
    "Rep_ID": {
      "type": "string"
    },
    "CUST_EDP": {
      "type": "number"
    },
    "CUST_NO": {
      "type": "string"
    },
    "SalesRepFirstName": {
      "type": "string"
    },
    "SalesRepLastName": {
      "type": "string"
    },
    "SalesRepPhone": {
      "type": "string"
    },
    "OrderStatuses": {
      "type": "array",
      "items": {
        "title": "OrderStatuses",
        "type": "object",
        "properties": {
          "SLOTID": {
            "type": "number"
          },
          "CUST_EDP": {
            "type": "number"
          },
          "SALES_ORD_NR": {
            "type": "string"
          },
          "OrderDate": {
            "type": "string"
          },
          "STATUS": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    }
  },
  "additionalProperties": true

Hi stauer_telephonyOne,

Can you give an example of the problematic response from your endpoint?

$rawResult is a simple string of the entire response from the endpoint, so $rawResult.CUST_CD doesn't work as it doesn't know anything about the key value pairs inside. You could look into using the template map to rip out each part of the response that you want and then put them back together in the success template. However, it might be possible to do a small string replacement to fix this issue, but that all depends on what exactly the endpoint is returning.

--Jason

{
  "rawResult": "{\n  \"CUST_CD\" : \"0132758228\",\n  \"CUST_EDP_ID\" : 7983815,\n  \"LNAME\" : \"JACKSON\",\n  \"FNAME\" : \"BETTY\",\n  \"STREET\" : \"71 DALE ST\",\n  \"CITY\" : \"ROCHESTER\",\n  \"STATE\" : \"NY\",\n  \"ZIP\" : \"146214603\",\n  \"DAY_PHONE\" : \"5852664246\",\n  \"NIGHT_PHONE\" : \"5852664246\",\n  \"FAX_PHONE\" : \"5857584975\",\n  \"Memberstatus\" : \"A\",\n  \"Account_Type\" : \"BR\",\n  \"Rep_ID\" : \"\",\n  \"CUST_EDP\" : 7983815,\n  \"CUST_NO\" : \"0132758228\",\n  \"OrderStatuses\" : [ null ]\n}"
}

It seems to me that the endpoint return an array with "null" in it instead of an empty array is pretty problematic behavior. I would suggest pushing the endpoint owner to fix that.

For now, doing something like this to clear out this array problem may be a bandaid for your issue:

"successTemplate": "$rawResult.replace(\"[ null ]\", \"[ ]\")"

--Jason

How is returning null problematic since it is valid JSON?

This works for now as a bandaid as you suggested. I will look at having the API changed to return and empty array instead of null since the client can't handle the Null.

"successTemplate": "$rawResult.replace(\"[ null ]\", \"[ ]\")"

Thank You.

How is returning null problematic since it is valid JSON?

So it is valid JSON, but it would mean that the schema for this part of the response is an array of "Either an object with these fields OR null". Unless a list that contains a "null" was supposed to mean something different then an empty list it is needless complexity.

--Jason

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.