Skip to content

Commit

Permalink
Enhance SetValueAt method for JSON manipulation; add error handling a…
Browse files Browse the repository at this point in the history
…nd support for insert, remove, and append actions. Introduce unit tests for ComplexTransform.
  • Loading branch information
grongierisc committed Jan 10, 2025
1 parent a0a93d1 commit 80d8764
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 23 deletions.
87 changes: 64 additions & 23 deletions src/iop/cls/IOP/Message.cls
Original file line number Diff line number Diff line change
Expand Up @@ -157,58 +157,99 @@ Method CopyValues(
Return tSC
}

/// Sets a value at the specified property path in the JSON document
/// @param pValue Value to set
/// @param pPropertyPath Path to the property (e.g. "property1.property2" or "array()")
/// @param pAction Action to perform ("set", "append", "remove", "insert")
/// @param pKey Optional key for specialized operations, required for insert
/// @returns %Status
Method SetValueAt(
pValue As %String = "",
pPropertyPath As %String = "",
pAction As %String = "set",
pKey As %String = "") As %Status
{
Set tSC = $$$OK
// if pAction is set, use jsonpath to set the value
Try {
if pAction = "append" {
// trinm () from the end of the path
if $EXTRACT(pPropertyPath, *) = ")" {
Set pPropertyPath = $EXTRACT(pPropertyPath, 1, $LENGTH(pPropertyPath)-2)
}
}
// Convert pPropertyPath to a a jsonpath
Set tPath = ..ConvertPath(pPropertyPath)
// Validate input parameters
If pPropertyPath = "" Return $$$ERROR($$$GeneralError, "Property path cannot be empty")
If '$LISTFIND($LISTBUILD("set","append","remove","insert"), pAction) Return $$$ERROR($$$GeneralError, "Invalid action: "_pAction)
If (pAction = "insert") && (pKey = "") Return $$$ERROR($$$GeneralError, "Key is required for insert action")

// Initialize Python objects
Set pyjson = ##class(%SYS.Python).Import("json")
Set jp = ##class(%SYS.Python).Import("jsonpath_ng")
Set builtins = ##class(%SYS.Python).Builtins()

// By default, if json is empty, set it to an empty object
if ..json = "" {
Set ..json = "{}"
// Handle append operations
Set tAppend = (pAction = "append")
If tAppend, $EXTRACT(pPropertyPath, *-1, *) = "()" {
Set pPropertyPath = $EXTRACT(pPropertyPath, 1, *-2)
}
Set tJSON = pyjson.loads(..json)

// Initialize empty JSON if needed
Set:..json="" ..json = "{}"

// Parse JSON and prepare path
Set tJSON = pyjson.loads(..json)
Set tPath = ..ConvertPath(pPropertyPath)
Set parser = jp.parse(tPath)
if pAction = "set" {

If pAction = "set" {
// Simple set operation
Set tJSON = parser."update_or_create"(tJSON, pValue)
}
ElseIf pAction = "append" {
ElseIf pAction = "remove" {
// Remove operation
Set matches = parser.find(tJSON)
If matches."__len__"() > 0 {
// Not yet implemented
Set tSC = $$$ERROR($$$GeneralError, "Remove operation not yet implemented")
}
}
ElseIf pAction = "insert" {
// Handle dictionary insert/update
Set matches = parser.find(tJSON)
If matches."__len__"() = 0 {
// Create new dictionary if path doesn't exist
Set tDict = builtins.dict()
Do tDict."__setitem__"(pKey, pValue)
Set tJSON = parser."update_or_create"(tJSON, tDict)
}
Else {
// Update existing dictionary
Set tDict = matches."__getitem__"(0)."value"
Do tDict."__setitem__"(pKey, pValue)
Set tJSON = parser."update"(tJSON, tDict)
}
}
ElseIf tAppend {
// Handle append operation
Set tFindValue = parser."find"(tJSON)
if tFindValue."__len__"() = 0 {
Set tList = builtins.list()
Do tList.append(pValue)
Set tJSON = parser."update_or_create"(tJSON,tList)
If tFindValue."__len__"() = 0 {
// Create new array if path doesn't exist
Set:(tAppend) tValue = builtins.list()
Do:tAppend tValue.append(pValue)
Set tJSON = parser."update_or_create"(tJSON, $Select(tAppend: tValue, 1: pValue))
}
Else {
// Append to existing array
Do tFindValue."__getitem__"(0)."value".append(pValue)
Set tJSON = parser."update"(tJSON, tFindValue."__getitem__"(0)."value")
}
}

Set tResult = pyjson.dumps(tJSON)
Set ..json = tResult
// Update JSON storage
Set ..json = pyjson.dumps(tJSON)
Set ..classname = ..DocType

} Catch ex {

}
Catch ex {
Set tSC = ex.AsStatus()
// Log error details
$$$LOGWARNING("Error in SetValueAt: "_$System.Status.GetErrorText(tSC))
}

Return tSC
}

Expand Down
23 changes: 23 additions & 0 deletions src/tests/cls/ComplexTransform.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Class UnitTest.ComplexTransform Extends Ens.DataTransformDTL [ DependsOn = IOP.Message ]
{

Parameter IGNOREMISSINGSOURCE = 1;

Parameter REPORTERRORS = 1;

Parameter TREATEMPTYREPEATINGFIELDASNULL = 0;

XData DTL [ XMLNamespace = "http://www.intersystems.com/dtl" ]
{
<transform sourceClass='IOP.Message' targetClass='IOP.Message' sourceDocType='registerFilesIop.message.ComplexMessage' targetDocType='registerFilesIop.message.ComplexMessage' create='new' language='objectscript' >
<assign value='source.{post}' property='target.{post}' action='set' />
<foreach property='source.{list_str()}' key='k1' >
<assign value='source.{list_str(k1)}_"foo"' property='target.{list_str()}' action='append' />
</foreach>
<foreach property='source.{list_post()}' key='k2' >
<assign value='source.{list_post().Title}' property='target.{list_post(k2).Title}' action='append' />
</foreach>
</transform>
}

}

0 comments on commit 80d8764

Please sign in to comment.