Single Value from a JSON object using JSONPath

Single Value from a JSON object using JSONPath
Extracts an arbitrary value from the JSON text stored in a String-type Data Item and sets it to another String-type Data Item or Numeric-type Data Item. It can be used for extracting necessary data from JSON received by the Webhook feature for example. JsonPath is used to specify the value.
2018 © Questetra, Inc. (MIT License)
Configs
  • A: Select STRING DATA for JSON Text *
  • B: Select STRING/SELECT DATA for JSONPath *
  • C: Select STRING/NUMERIC DATA for JSON Value (update) *
Script
// About JSON Path
// - see http://jsonpath.com/


//// == Config Retrieving / 工程コンフィグの参照 ==
var dataIdA = configs.get( "conf_DataIdA" ) + "";
var dataIdB = configs.get( "conf_DataIdB" ) + "";
var dataIdC = configs.get( "conf_DataIdC" ) + "";
// convert 'java.lang.String' to 'javascript string'


//// == Data Retrieving / ワークフローデータの参照 ==
var jsonText = engine.findDataByNumber( dataIdA ) + "";
var pathText = "";
if( engine.findDataDefinitionByNumber( dataIdB ).matchDataType( "SELECT_SINGLE" ) ){
    pathText = engine.findDataByNumber( dataIdB ).get(0).getValue() + "";
}else{
    pathText = engine.findDataByNumber( dataIdB ) + "";
}


//// == Calculating / 演算 ==
/* JSONPath 0.8.5 - XPath for JSON
 *
 * Copyright (c) 2007 Stefan Goessner (goessner.net)
 * Licensed under the MIT (MIT-LICENSE.txt) licence.
 *
 * Proposal of Chris Zyp goes into version 0.9.x
 * Issue 7 resolved
 */
function jsonPath(obj, expr, arg) {
   var P = {
      resultType: arg && arg.resultType || "VALUE",
      result: [],
      normalize: function(expr) {
         var subx = [];
         return expr.replace(/[\['](\??\(.*?\))[\]']|\['(.*?)'\]/g, function($0,$1,$2){return "[#"+(subx.push($1||$2)-1)+"]";})  /* http://code.google.com/p/jsonpath/issues/detail?id=4 */
                    .replace(/'?\.'?|\['?/g, ";")
                    .replace(/;;;|;;/g, ";..;")
                    .replace(/;$|'?\]|'$/g, "")
                    .replace(/#([0-9]+)/g, function($0,$1){return subx[$1];});
      },
      asPath: function(path) {
         var x = path.split(";"), p = "$";
         for (var i=1,n=x.length; i<n; i++)
            p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']");
         return p;
      },
      store: function(p, v) {
         if (p) P.result[P.result.length] = P.resultType == "PATH" ? P.asPath(p) : v;
         return !!p;
      },
      trace: function(expr, val, path) {
         if (expr !== "") {
            var x = expr.split(";"), loc = x.shift();
            x = x.join(";");
            if (val && val.hasOwnProperty(loc))
               P.trace(x, val[loc], path + ";" + loc);
            else if (loc === "*")
               P.walk(loc, x, val, path, function(m,l,x,v,p) { P.trace(m+";"+x,v,p); });
            else if (loc === "..") {
               P.trace(x, val, path);
               P.walk(loc, x, val, path, function(m,l,x,v,p) { typeof v[m] === "object" && P.trace("..;"+x,v[m],p+";"+m); });
            }
            else if (/^\(.*?\)$/.test(loc)) // [(expr)]
               P.trace(P.eval(loc, val, path.substr(path.lastIndexOf(";")+1))+";"+x, val, path);
            else if (/^\?\(.*?\)$/.test(loc)) // [?(expr)]
               P.walk(loc, x, val, path, function(m,l,x,v,p) { if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"), v instanceof Array ? v[m] : v, m)) P.trace(m+";"+x,v,p); }); // issue 5 resolved
            else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step]  phyton slice syntax
               P.slice(loc, x, val, path);
            else if (/,/.test(loc)) { // [name1,name2,...]
               for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++)
                  P.trace(s[i]+";"+x, val, path);
            }
         }
         else
            P.store(path, val);
      },
      walk: function(loc, expr, val, path, f) {
         if (val instanceof Array) {
            for (var i=0,n=val.length; i<n; i++)
               if (i in val)
                  f(i,loc,expr,val,path);
         }
         else if (typeof val === "object") {
            for (var m in val)
               if (val.hasOwnProperty(m))
                  f(m,loc,expr,val,path);
         }
      },
      slice: function(loc, expr, val, path) {
         if (val instanceof Array) {
            var len=val.length, start=0, end=len, step=1;
            loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g, function($0,$1,$2,$3){start=parseInt($1||start);end=parseInt($2||end);step=parseInt($3||step);});
            start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
            end   = (end < 0)   ? Math.max(0,end+len)   : Math.min(len,end);
            for (var i=start; i<end; i+=step)
               P.trace(i+";"+expr, val, path);
         }
      },
      eval: function(x, _v, _vname) {
         try { return $ && _v && eval(x.replace(/(^|[^\\])@/g, "$1_v").replace(/\\@/g, "@")); }  // issue 7 : resolved ..
         catch(e) { throw new SyntaxError("jsonPath: " + e.message + ": " + x.replace(/(^|[^\\])@/g, "$1_v").replace(/\\@/g, "@")); }  // issue 7 : resolved ..
      }
   };
   var $ = obj;
   if (expr && obj && (P.resultType == "VALUE" || P.resultType == "PATH")) {
      P.trace(P.normalize(expr).replace(/^\$;?/,""), obj, "$");  // issue 6 resolved
      return P.result.length ? P.result : false;
   }
} 
/// JSONPath end


// parse for API Request
var jsonObj = JSON.parse( jsonText );

// the return value of jsonPath is an array, which is also a valid JSON structure
var valueArray = jsonPath( jsonObj, pathText );


//// == Data Updating / ワークフローデータへの代入 ==
if( engine.findDataDefinitionByNumber( dataIdC ).matchDataType( "DECIMAL" ) ){
    var returnValue =  parseFloat( valueArray[0] );
    engine.setDataByNumber( dataIdC, java.math.BigDecimal(returnValue) );
}else{
    engine.setDataByNumber( dataIdC, ( valueArray[0] + "" ) );
}

Download

  • JsonValue-Extractor.xml
    • Since Rhino (deprecated) is specified as the script engine, a setting error will occur even if you install this in a workflow App
    • To use this Add-on, you need to change the script engine and modify the script accordingly
    • A modified version is in preparation

Capture

Notes

  • When JSONPath indicates multiple values (array value), the first value is set
  • When character information is stored as Numeric type data, it conforms to the specification of parseFloat ()
    (“+ 3.14”: 3.14, “314e-2”: 3.14, “090”: 90, “2016-12-23”: 2016, ‘start with character’: 0)
  • It is desirable that JSONPath Syntax is tested with sample data beforehand
Scroll to Top

Discover more from Questetra Support

Subscribe now to keep reading and get access to the full archive.

Continue reading