記事へ ima · 2024年7月7日 以下は、PythonからObjectScriptを呼び出す場合のJSONデータの渡し方のサンプルです。 Class Py.Demo2 Extends %RegisteredObject { /// d ##Class(Py.Demo2).Test() /// PythonからObJectScriptを呼び出す場合のJSONデータの渡し方案 /// ObJectScriptを呼び出す前後で、Python型からObJectScript型に変換/逆変換する ClassMethod Test() [ Language = python ] { import iris import json list = [1.23456789012345678901234,True,False,None,0,1,''] dict = {'A':33,'a':'lower case','漢字':'日本'} dict['list'] = list #; ObjectScript型へ変換 osdict = iris.cls("%DynamicObject")._New()._FromJSON(json.dumps( dict , ensure_ascii=False )) oslist = iris.cls("%DynamicArray")._New()._FromJSON(json.dumps( list , ensure_ascii=False )) print(f'type(osdict) = {type(osdict)}') print(f'osdict = {osdict._ToJSON()}') print(f'type(oslist) = {type(oslist)}') print(f'oslist = {oslist._ToJSON()}') arg = iris.ref("引数参照渡し") print(f'type(arg)={type(arg)}') arf = iris.arrayref(dict) #; アレイ参照渡し dictのみでlistはエラー print(f'type(arf)={type(arf)}') print('ObjectScript Proc 呼出し') #;**************************** ret = iris.cls("Py.Demo2").OSProc( osdict , oslist , arg , arf ) #;**************************** print('ObjectScript Proc 終了') print(f'返値型 = {type(ret)}') print(f'返値 = {ret}') #; Python型へ変換 dict = json.loads(osdict._ToJSON()) list = json.loads(oslist._ToJSON()) print(type(dict)) print(dict) print(type(list)) print(list) print(f'arg.value={arg.value}') iris.execute('zw ^||TEST') ;#ネストはなし(dict['list']) #: 以下の iris.gref は、^||...はエラーになるのでNOP #; g = iris.gref('^||TEST') #; for key in g.keys([]): #; value = g[key] #; print(f'{key} = {value}') } ClassMethod OSProc(ByRef Obj As %DynamicObject, ByRef Arr As %DynamicObject, ByRef Arg, ByRef Arf) As %DynamicAbstractObject { s Obj.UPDATE="dict Python側で変更しました" s Arr."0"="list ここも変更しました" s Arg=Arg_" 追加しました" w !,"Obj=",Obj.%ToJSON() w !,"Arr=",Arr.%ToJSON() w ! zw Arf k ^||TEST m ^||TEST=Arf w !,"プロセス・プライベート・グローバル ^||TEST にセットしました",! q "Ok" #; dict で返す場合 #; s json = ##class(%SYS.Python).Builtins().Import("json") #; s dict = json.loads(Obj.%ToJSON()) #; q dict } } 実行結果 USER>d ##Class(Py.Demo2).Test() type(osdict) = <class 'iris.%Library.DynamicObject'> osdict = {"A":33,"a":"lower case","漢字":"日本","list":[1.2345678901234567,true,false,null,0,1,""]} type(oslist) = <class 'iris.%Library.DynamicArray'> oslist = [1.2345678901234567,true,false,null,0,1,""] type(arg)=<class 'iris.ref'> type(arf)=<class 'iris.arrayref'> ObjectScript Proc 呼出し Obj={"A":33,"a":"lower case","漢字":"日本","list":[1.2345678901234567,true,false,null,0,1,""],"UPDATE":"dict Python側で変更しました"} Arr=["list ここも変更しました",true,false,null,0,1,""] Arf("A")=33 Arf("a")="lower case" Arf("list")=4@%SYS.Python ; [1.2345678901234567, True, False, None, 0, 1, ''] ; <OREF> Arf("漢字")="日本" プロセス・プライベート・グローバル ^||TEST にセットしました ObjectScript Proc 終了 返値型 = <class 'str'> 返値 = Ok <class 'dict'> {'A': 33, 'a': 'lower case', '漢字': '日本', 'list': [1.2345678901234567, True, False, None, 0, 1, ''], 'UPDATE': 'dict Python側で変更しました'} <class 'list'> ['list ここも変更しました', True, False, None, 0, 1, ''] arg.value=引数参照渡し 追加しました ^||TEST("A")=33 ^||TEST("a")="lower case" ^||TEST("list")="4@%SYS.Python" ^||TEST("漢字")="日本" USER>
記事へ ima · 2024年7月6日 はじめまして、こんな方法は如何ですか? 出来るだけ、ObjectScript、Python、それぞれで、自身のデータ型で処理できるように、渡す前後で、相手のタイプに変換/逆変換出来れば、透過性がよくなるかもしれません。 Class Py.Demo Extends %RegisteredObject { /// d ##Class(Py.Demo).Test() ClassMethod Test() { set builtins = ##class(%SYS.Python).Builtins() set json = ##class(%SYS.Python).Builtins().Import("json") ;# ObjectScritタイプ set oslist=[1.23456789012345678901234,true,false,null,0,1,"","英語"] set osdict={"A":33,"a":"lower case","漢字":"日本"} set osdict.list=oslist ;# Pythonタイプに変換 set pydict = builtins.dict() ;この行余計かも set pydict = json.loads(osdict.%ToJSON()) set pylist = builtins.list() ;この行余計かも set pylist = json.loads(oslist.%ToJSON()) zw builtins.type(pydict) zw builtins.type(pylist) ;# Pythonタイプで引数参照で渡す ;# ******************* set ret = ##Class(Py.Demo).PythonProc( pydict , pylist ) ;# ******************* ;# 参照引数渡しなので、結果として、Python側で変更された値が、引数に反映される ;# ObjectScript型に戻す set osdict = {}.%FromJSON(..jsondumps(pydict)) set oslist = [].%FromJSON(..jsondumps(pylist)) #; 以下でも jsondumps 使わず、文字化けは解消します #;set osdict= {}.%FromJSON($zcvt($zcvt(json.dumps(pydict),"I","JS"),"I","JSON")) #;set oslist= [].%FromJSON($zcvt($zcvt(json.dumps(pylist),"I","JS"),"I","JSON")) w !,osdict.UPDATE w !,oslist."0" w ! #; 返値も、構造が分かれば、Pythonの組み込み関数を利用して分解し、ObjectScript型に変換 #; return タプル( dict , list ) を前提 set retdict = {}.%FromJSON(..jsondumps(ret."__getitem__"(0))) set retlist = [].%FromJSON(..jsondumps(ret."__getitem__"(1))) w ! zw retdict w ! zw retlist } ClassMethod jsondumps(str) As %SYS.Python [ Language = python ] { #; 文字化け対応のキーワード指定(ensure_ascii=False) #; ObjectScritで、キーワード引数指定の仕方が分からないので python クラスにする import json return json.dumps(str,ensure_ascii=False) } ClassMethod PythonProc(dict As %SYS.Python, list As %SYS.Python) As %SYS.Python [ Language = python ] { #; Python側では、自身のデータタイプでアクセス import json print(type(dict)) print(dict) print(type(list)) print(list) dict['UPDATE']='dict Python側で変更しました' list[0]='list ここも変更しました' return ( dict , list ) } } 処理結果 USER>d ##Class(Py.Demo).Test() 6@%SYS.Python ; <class 'dict'> ; <OREF> 6@%SYS.Python ; <class 'list'> ; <OREF> <class 'dict'> {'A': 33, 'a': 'lower case', '漢字': '日本', 'list': [1.2345678901234567, True,False, None, 0, 1, '', '英語']} <class 'list'> [1.2345678901234567, True, False, None, 0, 1, '', '英語'] dict Python側で変更しました list ここも変更しました retdict={"A":33,"a":"lower case","漢字":"日本","list":[1.2345678901234567,true,false,null,0,1,"","英語"],"UPDATE":"dict Python側で変更しました"} ; <DYNAMIC OBJECT> retlist=["list ここも変更しました",true,false,null,0,1,"","英語"] ; <DYNAMIC ARRAY> USER>