Question
Menno Voerman · Sep 20

Question about combine/merge json files

Hi All,

I would like to merge json files. From a BPL we're running an operation to get data from a REST service cursors. We would like to run the REST calls until no cursor is present in the response of the rest call.

This works fine, but I would like to combine/merge the json outcome and write it to the disk.

 

See my attempt below for merging 2 json files.

 

Class Test.TestClass
{

ClassMethod xxx() As %Status
{
    Set tSc    = $$$OK
    
    set jsonObj1 = {}.%FromJSON("C:\temp\1.json")
    set jsonObj2 = {}.%FromJSON("C:\temp\2.json")
    
    Do jsonObj1.%Remove("NextCursor")
    Do jsonObj2.%Remove("NextCursor")
    
    set obj2 = jsonObj2.%Get("OptOuts")
    
    Do jsonObj1.%Set("", obj2)

    Set objString = jsonObj1.%ToJSON()
    set formatter = ##class(%JSON.Formatter).%New()
    Do formatter.FormatToStream(jsonObj1, .Streamobj)
    
    Set ResponseStream = ##class(%Stream.FileBinary).%New()
    Set ResponseStream.Filename = "C:\temp\3.json"
      Do ResponseStream.CopyFrom(.Streamobj)
    Set tSC = ResponseStream.%Save()
    Do ResponseStream.%Close()    
    return tSc
}

}

This gives an outcome but there's an extra node created, see 3.json. I think this make sense if i check rule with  " Do jsonObj1.%Set("", obj2)".

Any advise is welcome how to solve this.

See atttached, 1.json, 2.json

3.json = current result

4.json = wanted result

Product version: IRIS 2020.1
$ZV: IRIS for Windows (x86-64) 2020.1 (Build 215U) Mon Mar 30 2020 20:14:33 EDT [HealthConnect:2.1.0]
00
1 0 4 85
Log in or sign up to continue

Hi Menno,

Currently your solution creates an "extra" node because of the code Do jsonObj1.%Set("", obj2). %Set will always create a new node with parameter 1 as the key and parameter 2 as the value.

It seems like what you really want to do is append all of the objects in obj2.OptOuts with obj1.OptOuts. You can do this by iterating through Obj2.OptOuts and using %Push to append each to Obj1.OptOuts. I've modified the code you provided to accomplish this:

Class Test.TestClass
{
  ClassMethod xxx() As %Status
  {
    Set tSc = $$$OK

    Set jsonObj1 = {}.%FromJSON("C:\temp\1.json")
    Set jsonObj2 = {}.%FromJSON("C:\temp\2.json")

    Do jsonObj1.%Remove("NextCursor")
    Do jsonObj2.%Remove("NextCursor")

    Set obj1 = jsonObj1.%Get("OptOuts")
    Set obj2 = jsonObj2.%Get("OptOuts")

    Set OptOuts2Iter = obj2.%GetIterator()
    While OptOuts2Iter.%GetNext(.key , .value ) {
      Do obj1.%Push(value)
    }

    Set objString = jsonObj1.%ToJSON()
    Set formatter = ##class(%JSON.Formatter).%New()
    Do formatter.FormatToStream(jsonObj1, .Streamobj)

    Set ResponseStream = ##class(%Stream.FileBinary).%New()
    Set ResponseStream.Filename = "C:\temp\3.json"
    Do ResponseStream.CopyFrom(.Streamobj)
    Set tSc = ResponseStream.%Save()
    Do ResponseStream.%Close()
    Return tSc
  }
}

If I understand you correctly, all you have to do is a short loop:

ClassMethod Merge(obj...)
{
   set res=obj(1)
   do res.%Remove("NextCursor")
   for i=2:1:obj do res.OptOuts.%Push(obj(i).OptOuts)
   quit res
}
do Merge(json1, json2, json3, ...)

Of course, my loop is a little bit too short ;-(  the correct one is

ClassMethod Merge(obj...) {
   set res=obj(1)
   do res.%Remove("NextCursor")
   for i=2:1:obj {
      for j=0:1:obj(i).OptOuts.%Size()-1 do res.OptOuts.%Push(obj(i).OptOuts.%Get(j))
   }
   quit res
}

 Sorry, it seems, a telephone call and writing  does not go together.

Thank you @Alister Pino and @Julius Kavay for your help.

In this scenario see the final solution below:

ClassMethod MergeDynamicObjects(ObjComplete As %Library.DynamicObject, ObjAddendum As %Library.DynamicObject) [ Final ]
{
  Set obj1 = ObjComplete.%Get("OptOuts")
  Set obj2 = ObjAddendum.%Get("OptOuts")     
  Set OptOuts2Iter = obj2.%GetIterator()
  While OptOuts2Iter.%GetNext(.key , .value ) {
    Do obj1.%Push(value)
  }
  return ObjComplete
}