Question
Utsavi Gajjar · Jul 28

Cleaning up null elements from JSON payload

Hello All,

I am just wondering if there is any inbuilt function or utility available in IRIS to clean up "null" elements from JSON e.g. I want to remove "null" elements from payload below before I do any processing with it.

{

recipients: [ 

{ "name":"Utsavi", "email":"utsavi@gmail.com"},

{ "name":"Utsavi 1", "email":"utsavi1@gmail.com"},

null, null

],

content:[null, {"title":"Test.pdf", "data":"ygwehfbnwfbhew"} ]

}

Thanks & Regards,

Utsavi

 

Product version: IRIS 2021.1
00
1 0 9 100
Log in or sign up to continue

I think this may help

ClassMethod CleanNull(json As %DynamicObject) As %DynamicObject
{
  Set iter = json.%GetIterator()
  Set toRemove = ""
  While iter.%GetNext(.key, .value) {
    Set type = json.%GetTypeOf(key)
    If (type="null") {
      Set toRemove = toRemove _ $Listbuild(key)
    }
    ElseIf (type="object")||(type="array") {
      Set $Property(json, key) = ..CleanNull(value)
    }
  }
  Set ptr = 0, corr = 0
  While $Listnext(toRemove, ptr, key) {
    Do json.%Remove(key - corr)
    set corr = corr + 1
  }
  Return json
}

And Testing metho

ClassMethod TestJSON()
{
  set json = {
    "recipients": [ 
      { "name":"Utsavi", "email":"utsavi@gmail.com"},
      { "name":"Utsavi 1", "email":"utsavi1@gmail.com"},
      null, null
    ],
    "content":[null, {"title":"Test.pdf", "data":"ygwehfbnwfbhew"} ]
  }
  Set result = ..CleanNull(json)
  Do result.%ToJSON()
}

Will return this

{"recipients":[{"name":"Utsavi","email":"utsavi@gmail.com"},{"name":"Utsavi 1","email":"utsavi1@gmail.com"}],"content":[{"title":"Test.pdf","data":"ygwehfbnwfbhew"}]}

Perfect ! Thanks very much Dmitry :) 

Just create a simple method like this:

ClassMethod RemoveNull(obj)
{
   set iter=obj.%GetIterator()
   while iter.%GetNext(.key,.val) {
   if $isobject(val) { do ..RemoveNull(val) } elseif obj.%GetTypeOf(key)="null" { do obj.%Remove(key) }
}

gives you

set json={"recipients": [{ "name":"Utsavi", "email":"utsavi@gmail.com"},{ "name":"Utsavi 1", "email":"utsavi1@gmail.com"},null, null],"content":[null, {"title":"Test.pdf", "data":"ygwehfbnwfbhew"} ]}

write json.%ToJSON() --> {"recipients":[{"name":"Utsavi","email":"utsavi@gmail.com"},{"name":"Utsavi 1","email":"utsavi1@gmail.com"},null,null],"content":[null,{"title":"Test.pdf","data":"ygwehfbnwfbhew"}]}

write ##class(some.class).RemoveNull(json) --> {"recipients":[{"name":"Utsavi","email":"utsavi@gmail.com"},{"name":"Utsavi 1","email":"utsavi1@gmail.com"},null],"content":[{"title":"Test.pdf","data":"ygwehfbnwfbhew"}]}

Be careful with multiple %Remove, it moves the index. So, the next %Remove in a row, will remove the wrong item. 

USER>set json = [0,1,2]                                                                                     

USER>set json = [0,1,2], iter = json.%GetIterator()

USER>while iter.%GetNext(.key, .val){ write !,"[",key,"]=",val do:key=0 json.%Remove(key) }

[0]=0
[1]=2
USER>zw json
json=[1,2]  ; <DYNAMIC ARRAY>

And even with %Remove will not reach subsequent items

OK, this is the correct(ed) version:

ClassMethod RemoveNull(obj)
{
   set iter=obj.%GetIterator(),  rem=[]
   while iter.%GetNext(.key,.val) {
      if $isobject(val) { do ..RemoveNull(val) } elseif obj.%GetTypeOf(key)="null" { do rem.%Push({"o":(obj), "k":(key)}) }
   }
   for i=rem.%Size()-1:-1:0 set tmp=rem.%Get(i) do tmp.o.%Remove(tmp.k)
}

Thanks for the hint, I saw the problem right after answering.
Do we have a backwards-%GetNext(), i.e. an %GetPrevious()?

JSON is binary in a low level, so, the same as for $listbuild, I think only one way to go, and it is from begin to end