json モジュールについて (2)¶
数式処理 json5 parser コマンド¶
json5にて、 数式処理 をできるようにしたpython json5 parser.
ルール¶
文字列を与えた際は、常に、try する.
一方で、普通の文字列との区別がつかないので、エラーはでない.
エラーをだすには オプショナル引数として、"verbose=True" を与える.
または、数式は文字式で与え、文字式内にバッククォートで囲まれた領域を持つものとする
formula_mark=" ` "として与える.
" ` (数式) ` " という構成.
バッククォート前後の空白は許すが、空白以外があると感知されない.
正規表現的には、 r"\s*`([\s\S]+)`\s*"
引数のexpr_fmlで正規表現を与えれば、 変更も可能 .
変数は"変数マークをつけた語"で記載.(e.g. ${...} :ShellScript 環境変数 -like)
前後での空白は許すが、括弧内や$マークとの間の空白は許さない
{}はあってもなくてもよい.
正規表現例(@のとき): "@\{*[varname]\}*\s*" ( [varname] は登録変数名、総当りで検索. )
その他、空白は許されるはず.
変数名に 正規表現でエスケープが必要となる文字 を使用する際は注意( "."など.)
parser 関数( コード )¶
import json5, re, math, sys
import numpy as np
# ========================================================= #
# === json__formulaParser.py === #
# ========================================================= #
def json__formulaParser( inpFile=None, stop__error=False, verbose=False, table=None, \
expr_fml=None, formula_mark="", variable_mark="$" ):
if ( expr_fml is None ):
if ( formula_mark == "`" ):
expr_fml = r"\s*`([\s\S]+)`\s*"
elif ( formula_mark == "" ):
expr_fml = r"([\s\S]+)"
else:
print( "[json__formulaParser.py] formula_mark == {} ??? ".format( variable_mark ) )
sys.exit()
if ( variable_mark in [ "$" ] ):
variable_mark = "\{}".format( variable_mark )
# ------------------------------------------------- #
# --- [1] load json file as json5 --- #
# ------------------------------------------------- #
with open( inpFile, "r" ) as f:
varDict = json5.load( f )
if ( table is not None ):
varDict = { **table, **varDict }
# ------------------------------------------------- #
# --- [2] convert formula string into value --- #
# ------------------------------------------------- #
for key,val in varDict.items():
if ( type(val) is str ):
match_fml = re.match( expr_fml, val )
if ( match_fml ):
formula = match_fml.group(1)
for var_,val_ in varDict.items():
expr_from = variable_mark+"\{*"+var_+"\}*\s*"
expr_into = "{}".format( val_ )
formula = re.sub( expr_from, expr_into, formula )
try:
varDict[key] = eval( formula )
except SyntaxError:
if ( verbose ):
print()
print( "[json__wformula.py] Cannot evaluate [ERROR]" )
print( "[json__wformula.py] key :: {}".format( key ) )
print( "[json__wformula.py] formula :: {}".format( val ) )
print( "[json__wformula.py] :: {}".format( formula ) )
print()
except:
if ( verbose ):
print()
print( "[json__wformula.py] Cannot evaluate [ERROR]" )
print( "[json__wformula.py] key :: {}".format( key ) )
print( "[json__wformula.py] formula :: {}".format( val ) )
print( "[json__wformula.py] :: {}".format( formula ) )
print()
raise
# ------------------------------------------------- #
# --- [4] print parsed items --- #
# ------------------------------------------------- #
return( varDict )
# ========================================================= #
# === Execution of Pragram === #
# ========================================================= #
if ( __name__=="__main__" ):
# ------------------------------------------------- #
# --- [1] declare regexp and file name --- #
# ------------------------------------------------- #
inpFile = "test/json__formulaParser/sample1.json"
ret = json__formulaParser( inpFile=inpFile, variable_mark="$" )
print( ret )
# ------------------------------------------------- #
# --- [2] variable mark is "@" case --- #
# ------------------------------------------------- #
inpFile = "test/json__formulaParser/sample2.json"
ret = json__formulaParser( inpFile=inpFile, variable_mark="@" )
print( ret )
{'string': 'This is a pen', 'val1': 30.0, 'val2': 2, 'arr1': [1.0, 2.0, 3.0], 'sw1': True, 'sw2': False, 'item': None, 'fml': 1.7320508075688774, 'fml2': 1.0000000000000002, 'val3': 60.0}
json サンプル¶
{
// This is a sample of json file
"string" :"This is a pen",
"val1" : 30.0,
"val2" : 2,
"arr1" : [1.0,2.0,3.0,],
"sw1" :true,
"sw2" :false,
"item" :null,
"fml" : " ` np.cos(${val1}/180.0*np.pi) * ${val2} ` ",
"fml2" : " ` np.cos(${val3}/180.0*np.pi) * ${val2} ` ",
"val3" : 60.0,
"val4" : " ` ${val1} + ${val2} ` ",
"val5" : " ` ${val3} * ${val4} ` ",
"val6" : " ` ${val5} / ${val1} ` ",
/* comment line */
}