みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。
1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)
You are not logged in.
Pages: 1
いつもお世話になっております。
JSONでのデータの追加の仕方が分からず困っております。
使用環境
FMpro17
windows 10
下記のデータAにデータBを追加したいのですが、どのようにすればよろしいでしょうか。
データは300件ほどあるのですが、一度に取得できるデータが100件までのため、最終一つのデータにしたいと考えております。
データA
{"product_stock":[{"id":1,"name":"アイボリー","product_id":5,"product_no":"A1234_1","stock":0,"stock_flag":1,"stock_parent":null},
{"id":2,"name":"ブラック","product_id":5,"product_no":"A1234_2","stock":2,"stock_flag":1,"stock_parent":null}],"meta":{"limit":2,"offset":0,"total":14}}
データB
{"product_stock":[{"id":3,"name":"アイボリー","product_id":6,"product_no":"B1234_1","stock":0,"stock_flag":1,"stock_parent":null},
{"id":4,"name":"ブラック","product_id":6,"product_no":"B1234_2","stock":2,"stock_flag":1,"stock_parent":null}],"meta":{"limit":2,"offset":0,"total":14}}
データAに追加
{"product_stock":[{"id":1,"name":"アイボリー","product_id":5,"product_no":"A1234_1","stock":0,"stock_flag":1,"stock_parent":null},
{"id":2,"name":"ブラック","product_id":5,"product_no":"A1234_2","stock":2,"stock_flag":1,"stock_parent":null},
{"id":3,"name":"アイボリー","product_id":6,"product_no":"B1234_1","stock":0,"stock_flag":1,"stock_parent":null},
{"id":4,"name":"ブラック","product_id":6,"product_no":"B1234_2","stock":2,"stock_flag":1,"stock_parent":null}]}
各データの最後の"meta"は不要のため、データ取得後、先にJSONDeleteElementで削除しよう考えております。
よろしくお願い致します。
Offline
最初に回答を投稿したのですが、よく見たらバグっていたので地道にスクリプトを書きました。
#meta情報を取り除いたJSONを取得
変数を設定 [ $json; 値:JSONDeleteElement ( データA ; "meta" ) ]
#"product_stock"のオブジェクト数を取得
変数を設定 [ $itemsOfA; 値:ValueCount ( JSONListValues ( データA ; "product_stock" ) ) ]
変数を設定 [ $itemsOfB; 値:ValueCount ( JSONListValues ( データB ; "product_stock" ) ) ]
#ループしながら値をマージ
変数を設定 [ $index; 値:0 ]
Loop
変数を設定 [ $json
; 値:JSONSetElement ( $json ;"product_stock[" & $itemsOfA + $index & "]"
; JSONGetElement ( データB ; "product_stock[" & $index & "]" )
; JSONObject ) ]
変数を設定 [ $index; 値:$index+1 ]
Exit Loop If [ $index ≥ $itemsOfB ]
End Loop
#マージ結果をフィールドに格納
フィールド設定 [ マージ結果; JSONFormatElements ( $json ) ]
Last edited by koeda (2020-05-20 09:05:35)
Offline
Offline
ループ計算式で求める式例、
Let(
[
$jsn=JSONDeleteElement(データA;"meta");
$nA=ValueCount(JSONListValues(データA;"product_stock"));
$nB=ValueCount(JSONListValues(データB;"product_stock"));
$i=0;
$LOOP=
"Case($i=$nB; JSONFormatElements($jsn);
Let([
$jsn=
JSONSetElement($jsn
; ""product_stock["" & $nA+$i & ""]""
; JSONGetElement(データB;""product_stock["" & $i & ""]"")
; JSONObject );
$i=$i+1
]; Evaluate($LOOP))
)"
];
Evaluate($LOOP)
)
Offline
Hiroさん、ありがとうございます。
再帰式を書くの苦手で…
Offline
koedaさん、Hiroさんありがとうございます。
教えていただいた方法でデータを追加することができました。
自分なりに別の追加方法も考えたのですが、下記のようなやり方はダメでしょうか。
変数を設定 [ $jsonA; 値:JSONDeleteElement ( データA ; "meta" ) ]
変数を設定 [ $jsonB; 値:JSONDeleteElement ( データB ; "meta" ) ]
変数を設定 [ $kekka;
Let ( [
$pos = Position ( $jsonB ; "[" ; 1 ; 1 ) ;
$len = Length ( $jsonB ) ;
$tsuika = Right ( $jsonB ; $len - $pos ) ] ;
Substitute ( $jsonA ; "]}" ; "," & $tsuika )
)
]
上記は、受信した各データはエラーがない場合です。
よろしくお願い致します。
Offline
>#1でJSON関数が示唆されていたので、JSON関数で完結する方法をとりましたが、
#6のような従前のテキスト関数で処理するのも全然構わないと思いますよ。
(※ただし、従前のテキスト関数処理はデータのJSONフォーマット構文が固定的であまり自由度はありません。)
#6のスクリプトは、1つの計算式に纏めることもできます。
Let(
[
#jsnA=SONDeleteElement(データA;"meta");
#jsnB=SONDeleteElement(データB;"meta");
#pos=Position(#jsnB;"[";1;1);
#len=Length(#jsnB);
#add=Right(#jsnB;#len-#pos)
];
JSONFormatElements(Substitute(#jsnA; ["]}";","&#add]))
)
Offline
自分なりに別の追加方法も考えたのですが、下記のようなやり方はダメでしょうか。
今回は単純な構造のJSONなので全く問題ないと思います。
ただ今回作成したマージのアルゴリズムは他の場面でも使えると思うので、
今回Hiroさんの提示してくださった計算式をカスタム関数にし、
データA、データB、オブジェクト名の3つをパラメータとして渡せるようにしておけば
「JsonAに、JsonBのオブジェクト"hoge"をマージする」
という汎用的な関数に仕立てることができるのではないでしょうか。
Last edited by koeda (2020-05-20 09:42:07)
Offline
カスタム関数化したファイルです。
https://www.dropbox.com/s/1139fkg6ziu1r … fmp12?dl=0
(追記)あとから気づきましたが、汎用化するならJSONFormatElements ( )による整形はしない方が良いですね。
Last edited by koeda (2020-05-20 13:16:30)
Offline
前回答案でネックの面倒なループ処理を使わず、本案件に特化・最適化した安楽な互換式の提案です。
Let(
[
#jsnA=JSONGetElement(データA;"product_stock");
#jsnB=JSONGetElement(データB;"product_stock");
#jsnAB=Substitute(List(#jsnA;#jsnB);["]¶[";","]);
#jsn=JSONSetElement(""; "product_stock"; #jsnAB; JSONArray)
];
JSONFormatElements(#jsn)
)
Offline
koedaさん、Hiroさん
いろいろ教えていただきありがとうございます。
早速試してみたいと思います。
Offline
>#1『データは300件ほどあるのですが、一度に取得できるデータが100件までのため、最終一つのデータにしたいと考えております。』
この初期説明からすると、マージ対象データは2つだけでなく、3つ以上と云う事ですかネ?
なら、#10式の2つデータ対応を任意数のマルチデータに対応した修正式を以下に補足。
(※仮に、データAから任意データXまでとして式記述)
Let(
[
#jsnA=JSONGetElement(データA;"product_stock");
#jsnB=JSONGetElement(データB;"product_stock");
・・・
・・・
#jsnX=JSONGetElement(データX;"product_stock");
#jsnA2X=Substitute(List(#jsnA;#jsnB;・・・;#jsnX);["]¶[";","]);
#jsn=JSONSetElement(""; "product_stock"; #jsnA2X; JSONArray)
];
JSONFormatElements(#jsn)
)
Offline
Hiroさん、ありがとうございます。
返信が遅くなってすみません。
ここまでスッキリできるんですね(^^;)
大変勉強になりました。
ありがとうございます。
Offline
Pages: 1
[ Generated in 0.005 seconds, 9 queries executed - Memory usage: 550.91 KiB (Peak: 571.82 KiB) ]