//============================================================================== // cJsonPath.pkg // // A class which will allow you to get either object handles or values from JSON // objects using their path. // // Author: Mike Peat // Date: 06/02/2020 // // Usage: // To return a JSON object at a path: // Get JsonAtPath of oJsonPathObject hoSourceJsonObject, path to hoVar // Or: // Move (JsonAtPath(oJsonPathObject, hoSourceJsonObject, path)) to hoVar // // To return a value at a path: // Get ValueAtPath of oJsonPathObject hoSourceJsonObject path to sVar // Or // Move (ValueAtPath(oJsonPathObject, hoSourceJson, path)) to sVar // // Path notation: // // A string with JSON object names, separated by dots "." and array indices // in square brackets: "foo.bar.baz[0].bill[1][0]" // // Sample JSON: // // { // "foo": { // "bar": { // "baz": [ // 66.123, // { // "jim": "jack" // }, // False, // { // "bob": 42 // }, // { // "kim": "possible" // }, // [55, 1, 19, { // "Mork": [ // [35, 67, 88, 100, [21, 33, 45, "Tim"]] // ] // }] // ] // } // } // } // // Examples: // Move (JsonAtPath(oJPath, hoJson, "foo.bar.baz[5][3].Mork[0][4][3]")) to hoObj // // Get ValueAtPath of oJPath hJson "foo.bar.baz[5][3].Mork[0][4][3]" to sVal // (sVal = "Tim") // // In the first example the JSON object would be returned; if you then performed // Move (JsonValue(hoObj)) to sVal you would get the same result as the second // example - i.e. "Tim". // // NOTE: JSON is case-sensitive, so your path-strings must exactly match the // object names ("foo" is *not* "Foo") in the JSON file. // //============================================================================== Use UI Use cJsonObject.pkg Class cJsonPath is a cObject Function ArrayHandle Handle hoJson String sPath Returns Handle Integer iLSBPos iRSBPos iIndex Handle hoMemb hoObj If not hoJson ; Function_Return 0 If (sPath = "") Begin Send Destroy of hoJson Function_Return 0 End Move (Pos("[", sPath)) to iLSBPos Move (Pos("]", sPath)) to iRSBPos If (not(iLSBPos) or ; not(iRSBPos) or ; (iLSBPos > iRSBPos) or ; (iLSBPos <> 1)) Begin Send Destroy of hoJson Function_Return 0 End Move (Mid(sPath, (iRSBPos - iLSBPos - 1), (iLSBPos + 1))) to iIndex If (MemberCount(hoJson) <= iIndex) Begin Send Destroy of hoJson Function_Return 0 End Get MemberByIndex of hoJson iIndex to hoMemb If (Length(Trim(sPath)) = iRSBPos) Begin // It ends here Send Destroy of hoJson Function_Return hoMemb End Move (Right(sPath, (Length(sPath) - iRSBPos))) to sPath If (Left(sPath, 1) = ".") ; Move (Replace(".", sPath, "")) to sPath Get ObjectHandle hoMemb sPath to hoObj Send Destroy of hoJson Function_Return hoObj End_Function Function ObjectHandle Handle hoJson String sPath Returns Handle Integer iLSBPos iDotPos iPos String sMemb Handle hoMemb hoObj If not hoJson ; Function_Return 0 If (sPath = "") Begin Send Destroy of hoJson Function_Return 0 End If (Left(sPath, 1) = "[") ; Function_Return (ArrayHandle(Self, hoJson, sPath)) Move (Pos(".", sPath)) to iDotPos Move (Pos("[", sPath)) to iLSBPos If (iLSBPos and iDotPos) ; Move (iDotPos min iLSBPos) to iPos Else If (iDotPos) ; Move iDotPos to iPos Else ; Move iLSBPos to iPos If not iPos Begin // We are there! If (HasMember(hoJson, sPath)) Begin Get Member of hoJson sPath to hoMemb Send Destroy of hoJson Function_Return hoMemb End Else Begin Send Destroy of hoJson Function_Return 0 End End Move (Left(sPath, (iPos - 1))) to sMemb If (HasMember(hoJson, sMemb)) Begin Get Member of hoJson sMemb to hoMemb Send Destroy of hoJson Move (Right(sPath, (Length(sPath) - iPos + 1))) to sPath If (Left(sPath, 1) = ".") ; Move (Replace(".", sPath, "")) to sPath Get ObjectHandle hoMemb sPath to hoObj Function_Return hoObj End Send Destroy of hoJson Function_Return 0 End_Function Function JsonAtPath Handle hoJson String sPath Returns Handle Handle hoObj UChar[] ucaJson Boolean bOK If (not(hoJson) or (sPath = "")) ; Function_Return 0 // Do this to "copy" hoJson to hoObj, so hoJson does not get destroyed // in the process Get StringifyUtf8 of hoJson to ucaJson Get CreateNamed (RefClass(cJsonObject)) "CopyJson" to hoObj Get ParseUtf8 of hoObj ucaJson to bOK Function_Return (ObjectHandle(Self, hoObj, sPath)) End_Function Function ValueAtPath Handle hoJson String sPath Returns String Handle hoObj String sVal Integer iType Get JsonAtPath hoJson sPath to hoObj If hoObj Begin Get JsonType of hoObj to iType If ((iType <> jsonTypeObject) and ; (iType <> jsonTypeArray) and ; (iType <> jsonTypeNull)) ; Move (JsonValue(hoObj)) to sVal Send Destroy of hoObj End Function_Return sVal End_Function End_Class