質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Q&A

5回答

3386閲覧

C#でjsonファイルを編集したい!(少し?難あり)

nonki03

総合スコア11

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

1グッド

1クリップ

投稿2019/06/12 14:18

編集2019/06/15 01:25

現在3つのアプリを開発中で、それらは全て画面に表示する文言をjson形式にて管理する予定です。
他国でも使用されるアプリのため、その文言管理用jsonファイルは各国の文言を記載したものがそれぞれ用意されることとなります。
バージョンアップにて新しく文言が追加される度、英語を基準に各国の方が翻訳し、その国ごとの文言管理用jsonファイルを作成するための、技術者でない人でも扱えるような文言変更ツールが必要となります。
今回はその文言変更ツールの作成です。

ツールの開発環境はVS2008、Frameworkは3.5で作成しています。
その読み込むjsonファイルの中身が以下のような内容です。


{
"LoginScreen":{
"label_title":"Login Screen",
"label_userId":"User ID",
"label_password":"Password",
"button_login":"LOGIN"
←(増える可能性あり)
},
"UserLIstScreen":{
"label_title":"User List",
"label_userId":"User ID",
"label_userName":"User Name",
"label_userTell":"TEL",
"label_phone":"Phone",
"label_save":"SAVE"
←(増える可能性あり)
},
"SettingListScreen":{
"label_title":"Setting",
"label_storeName":"Store Name",
"label_language":"Language",
"button_save":"SAVE"
←(増える可能性あり)
}
←(更に他画面が増える)
}


画面ごとに区切られていて、その中にメッセージのkeyとvalue といった形になってます。
画面名・メッセージのkey・valueはそれぞれ全て動的な上、今後文言が増えることもありますし、画面が増えることもあります。
その度にツールを修正するようなことはしたくありません。

やりたいこととしては、
1.jsonファイルを読み込み、データをメモリに保持。
2.フォームのDataGridViewに値をセット、画面にて編集できるようにする。
(その際、変更された文言・追加された文言・既存文言が分かるようにする。)
3.保存ボタン押下時に、編集した新しいjsonファイルを排出。
といった内容です。

現在jsonファイルの読み込みの段階で、読み込むには別クラスによる型宣言が必要だと認識しているのですが、キーが動的なゆえに別クラスによる型宣言がうまくできず、どう読み込めばいいのか分からなくて詰まっています。
→なんとか読み込み、切り分け、画面に表示までできました。
ただ、やり方が少し強引というか…

C#

1 private void EditScreen_Load(object sender, EventArgs e) 2 { 3 4 5 try 6 { 7 var jScreen = JObject.Parse(File.ReadAllText("D:\MessageWork\En_Old\risou.json", Encoding.Default)); 8 9 foreach (var MenuMsg in jScreen.Properties()) 10 { 11 MessageBox.Show(Regex.Replace(MenuMsg.ToString(), ".*{", "{")); 12 var dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(Regex.Replace(MenuMsg.ToString(), ".*{", "{")); 13 string sss = ""; 14 foreach (var ScreenMsg in dic.Keys) 15 { 16 sss += ScreenMsg.ToString() + " : " + dic[ScreenMsg].ToString() + "\r\n"; 17 } 18 MessageBox.Show(sss); 19 20 } 21 22 } 23 catch (Exception ex) 24 { 25 string msg = string.Format("Error Occurred! \r\n\r\n{0}", ex.ToString()); 26 MessageBox.Show(msg); 27 } 28 }

JObject.Parseを使って画面ごとに切り出し、
切り出した後の左側の部分を無理やりReplaceでカット
JsonConverter.DeserialiseObjectを通して{}の部分を読み込み。
画面に表示…といった感じです。

出来た、としてもいいのですが、あまり綺麗ではないかな…と感じています。
これ以外に「この方法の方が良い」といったような方法は無いでしょうか…

x_x👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/06/12 20:28

質問に書かれた文字列は JSON として正しいですか? 転記ミスなら修正願います。
papinianus

2019/06/12 22:14

切り分けっていうところでやりたいことが分からないです。文言を取り出す瞬間に画面とキーは判明していますよね?それをインデクサとして取り出せばいいのでは? あとVB.NETができるならそれでjsonを解析するdllつくって呼べばいいのでは?
退会済みユーザー

退会済みユーザー

2019/06/12 23:12 編集

JSON 文字列をデシリアライズして C# のオブジェクトに変換するところで躓いていると理解していますが、「ツール」でそれができないのでは「開発中のソフト」でもできないわけで、なんか話が変です。きちんと話が伝えられていないような気がします。
退会済みユーザー

退会済みユーザー

2019/06/13 04:37

JSON 文字列を書き直したようですが、依然として JSON 形式として正しくないです。 あと、上の私のコメントに対しては何か返事はないのでしょうか?
退会済みユーザー

退会済みユーザー

2019/06/13 04:45

JSON 文字列をゼロから見直す余地はないのですか? 今の形で文法的に正しく直しても、要素の追加に対応するのはかなり難しそうです。
退会済みユーザー

退会済みユーザー

2019/06/13 04:48

あと、回答が 2 件出てますが、それらに対するフィードバックを書いてください。なしのつぶては大変失礼ですよ。
Zuishin

2019/06/13 04:49

データ形式が定まってないのならテキストエディタでやるのがベストです。 文字列をただ書き換えるだけなので、ツールを作っても負担が大きい割にそれ以上便利になるとは思えません。
Zuishin

2019/06/13 04:53

もしどうしても私が作らなければならないのであれば、TreeView と PropertyGrid を使ったエクスプローラ式の UI を作ります。Json のデコードはデータが小さくて型が無いので DynamicJson などを使うかもしれません。
Q71

2019/06/13 04:57

v3.5でSystem.Runtime.Serializatin.Json は使えないのですが(4以降) リソースとしてのテキストファイルを用意してもらい、リソースコンパイラでコンパイルするってのでいいのでは?なぜ茨の道を歩く?
nonki03

2019/06/13 05:54

>各質問者の方 すみません、今客先業務中で詳しくかけないので、夜になったらお答えします…
退会済みユーザー

退会済みユーザー

2019/06/13 08:03 編集

2019/06/13 13:44 の編集で JSON 文字列を正しく直したようですので、MiniJSON を使って Dictionary<string, object> にデシリアライズできます。シリアライズもできます。もちろん .NET 3.5 でも OK です。 DataContractJsonSerializer や Newtonsoft.Json のようにデシリアライズされる C# のクラスを定義しなければならない場合はページや要素の増減には対応困難ですが、MiniJSON はその必要はないので、 Dictionary<string, object> を扱うことができるなら、これが選択肢の第一候補になるのではと思います。
Q71

2019/06/13 08:05

上、取り消して訂正。 3.5でいけますね。最初のサンプルにDictionaryが使われていた。Dictionary<String, Dictionary<String, String>> でできます。
nonki03

2019/06/13 12:06

遅くなってすみません。 >SurferOnWww さん 度々の編集、失礼しました。 なにせjsonを扱うのが初めてなもので、まだ身についていない状態です。 今書かれているものが現在扱うとされている文字列となります。 この開発環境でやれると知って安心しました。 >papinianus さん JObject.Parseで切り分けた際、List型として画面ごとに1本1本、3つのデータで値を持っているようでした。 そのため、KeyとValueとして分かれて持っているわけではないと思い、 画面名(『"LoginScreen":』としている部分)の部分をどうにかできないかと考えていました。 またVB.NETですが、あくまで経験がある ぐらいの程度なので、 その発想には至りませんでした… >Zuishin さん 正直何故文言をjsonで管理しようとしてるのかよくわかりません。 おそらく、開発中の3つのアプリ間で通信する際にjsonを使用しようとしているゆえ…でしょうか…。 どうせわかりやすく編集できるツールを作るのならCSVでもなんでも もっと簡単なものでいいのではと感じています。 >Q71 さん 今日何とか無理やり取り込むことに成功しましたが、やり方がむちゃくちゃだったので、 その方法を参考にしてみようと思います。 >各質問者の方 今日無理やりですが、以下の方法で取り込み、画面に表示させるまではできました。 1.JObject.Parseにて画面ごとに取り込み(3本のデータ) "LoginScreen":{"label_title":"Login Screen","label_userId":"User ID","label… "UserLIstScreen":{"label_title":"User List","label_userId":"User ID","labe… "SettingListScreen":{"label_title":"Setting","label_storeName":"Store Nam… 2.ループでデータを1本ずつ取り出し、   Replaceを使用して正規表現で"{"より左をカット {"label_title":"Login Screen","label_userId":"User ID","label… 3.JsonConvert.DeserializeObjectにて文言ごとにkeyとValueで保持。 4.画面へ出力 正直ごり押し過ぎて自分でも「何やってんだろ…」と思いつつ、 Q71さんの一言でほかの方法を模索中の状態です。 正直jsonなんかで管理したくないので他の形式に変更できないか上司と相談して 取り合ってもらおうかと考えています…
Zuishin

2019/06/13 12:19

いやだから Json の編集はテキストエディタでできるしそれはごく普通の方法です。そのためのテキストフォーマットなので。
退会済みユーザー

退会済みユーザー

2019/06/13 13:14

先に私が書いた以下の疑問に答えていただけませんか? JSON 文字列をデシリアライズして C# のオブジェクトに変換するところで躓いていると理解していますが、「ツール」でそれができないのでは「開発中のソフト」でもできないわけで、なんか話が変です。
nonki03

2019/06/14 01:10

>Zuishin さん テキストエディタでも編集可能なのですが、実はこの3アプリは旧型がありまして… 旧型は文言をXMLで管理していたので、直接書き換えるのは面倒なのか文言の変更ツールが作成されていました。 そのツールは変更のあった文言は黄色・新しく追加されている文言は赤のように分かりやすく示してくれる機能があり、好評だったそうです。 比較機能のあるテキストエディタを使用すればそこもツールを作らずできる話なんですが、どうにもツールがいいそうで…。 >SurferOnWww さん 私が詰まっている部分は確かにそこです。 開発中のソフトはまだ基本設計段階でサンプル画面程度の開発しかできておらず、「文言はjsonで管理する」とだけ決まっているからツールを作成している…といった現状になります。 ソフトの方は他社さんが開発していて、今のところサンプル画面が作成されている程度、恐らくその部分に着手していないと思われます… (サンプル画面なら直値でやってそうですし…)
退会済みユーザー

退会済みユーザー

2019/06/14 02:16

他社との共同開発という事情は理解しました。 ・・・が、と言うことは他社との今後の話で、質問に書かれているJSON の構造が変わることがあるということですか? もしそうであれば、今はあまり JSON に知識がない質問者さんが仮に (?) 考えた構造らしいので、変わる可能性が大ということですよね。それでは、こういうところで他人に質問する段階ではないと思うのですが、いかがですか?
gentaro

2019/06/14 02:44

各回答には返信がなくここでやりとりされてるんですね。 まぁなんとなく事情は飲み込めましたが、作りたいのはJSONを読み込んで編集し、新しいJSONを吐くツールであって、そこに古いJSONと差分検知機能があればいい、という話なんですね。 ちょっとノイズになる情報(多言語対応云々)が多すぎる気がするので、質問内容を整理された方が良いんじゃないでしょうか。
gentaro

2019/06/14 02:48

なんとなくですが、JSONそのものを扱うんじゃなく、ただのテキスト形式のファイルとして読み込んで、C#上で使いやすいデータセットに突っ込んで編集し、編集結果を吐く時にJSON形式に則ったテキストファイルとして吐いてやる、という形で十分な気がします。これならシリアライズ・デシリアライズも関係ないし。
gentaro

2019/06/14 03:36

回答編集しておきました。
nonki03

2019/06/15 00:30

>SurferOnWww さん 書いているJSONのイメージ自体は私ではなく、受注先の方が考えられたものです。 今後扱うことが難しいようであれば、もしかするとJSONでなくなる可能性もあります。 そのことを踏まえるならここで他の人に質問するのも確かに良くないとは思いますが、あまりにも進捗が上がらなかったので苦渋の決断で質問した次第です… 不快に思われたのなら、申し訳ありません… >gentaro さん すみません…平日は他でやることが多く、質問欄と回答欄両方での長文返信というのが出来ていない状態です。 >作りたいのはJSONを読み込んで編集し、新しいJSONを吐くツールであって、そこに古いJSONと差分検知機能があればいい、という話なんですね。 そういう話です。一度質問内容を見直しておきます。
退会済みユーザー

退会済みユーザー

2019/06/15 02:34

> すみません…平日は他でやることが多く、質問欄と回答欄両方での長文返信というのが出来ていない状態です。 回答に対しては回答の下のコメント欄にフィードバックを書いてください。ここではそれがルールのようです。「平日は他でやることが多く」は質問者さんの都合・事情であって、回答者・閲覧者には関係ないことと思います。
退会済みユーザー

退会済みユーザー

2019/06/15 02:39

> 書いているJSONのイメージ自体は私ではなく、受注先の方が考えられたものです。 そうであれば、なぜ「受注先」からもらった情報を 2 回も間違えて書いたのか疑問ですが、それはちょっと置いといて・・・ JSON の形式はおろか、JSON を使うか否かさえもまだ未定ということであれば、そういう事情は最初の質問に書いておいていただけていたらと思います。回答者は、それを考えた回答ができますので。その方が質問者さんにとってもより役に立つ情報が得られるのではないかと思います。 > 扱うことが難しいようであれば、 JSON を使うことの是非についてはいろいろ意見があると思いますが、少なくとも、質問に書かれた JSON 文字列から全ての key と value のペアを取得することは可能です。 上にも書きましたが、MiniJSON を使って Dictionary<string, object> にデシリアライズできます。シリアライズもできます。もちろん .NET 3.5 でも OK です。質問に書かれていた「←(増える可能性あり)」にも対応できます。 サードパーティ製のライブラリを使うことに問題があれば、JavaScriptSerializer を使っても可能です。 取得した結果を「ツール」のエディタにどう表示して編集できるようにするかは別の話で、そこが一番難しいとは思いますが・・・ でも、もしまだ JSON 文字列をデシリアライズして C# のオブジェクトに変換するところで躓いているのであれば、それは簡単に解決できると思いますので、解決してからどうするか考えてみてはいかがでしょう。
gentaro

2019/06/15 05:12

色んなご意見あると思いますが、個人的には今回の開発要件と質問者がJSONのライブラリの使用方法で躓いてしまう事実を鑑みると、C#上で無理にJSONライブラリ等を使ってどうにかする方法を提案するよりも、私の回答に書いたような、ただの文字列加工のレベルに落とし込んでちゃっちゃと作ってしまった方が良いような気はします。これなら1年目のプログラマでもできると思いますので。 というより、JSONをデシリアライズして得られるメリットって、そのオブジェクトをC#でも「オブジェクト」として扱えることにあるわけで、コード上でプロパティ名とかでアクセスするような使い方ですよね。 そこが可変になる、という今回の要件から考えて、そもそも論としてアプローチがおかしいような気がしました。 インプット・アウトプットともにただの文字列なんだから、そんなに難しく考えんでも…という感じです。
nonki03

2019/06/16 02:50

>SurferOnWww さん >「平日は他でやることが多く」は質問者さんの都合・事情であって、回答者・閲覧者には関係ないことと思います。 確かにそうです…すみません。 >JSON の形式はおろか、JSON を使うか否かさえもまだ未定ということであれば、そういう事情は最初の質問に書いておいていただけていたらと思います。 わかりました、以後気を付けます… あと、2回も間違えて書いた件についてですが、 開発中のものなのでそのまま流すのはどうかと思い、自分で手書きしておりました。 そのため、記述ミスで何度か修正していたのです… 標準以外のライブラリを使うことは別に問題ないのですが、 他のライブラリを使用した方法を色々模索している余裕があまりないので、 今回は使える範囲でライブラリの機能を使って、 あとは文字列加工で何とかするようにしてみます。 >gentaroさん >JSONをデシリアライズして得られるメリットって、そのオブジェクトをC#でも「オブジェクト」として扱えることにあるわけで、コード上でプロパティ名とかでアクセスするような使い方ですよね。 そこが可変になる、という今回の要件から考えて、そもそも論としてアプローチがおかしいような気がしました。 言われてみれば確かにおかしいと思えてきました。 余談ですが、過去に扱ったjavaアプリの機能でxmlを取り込む機能をよく弄ることがあったので、 今回の"C#でjsonを取り込み" といったものでもガツガツと取ってこれるもんだと思い込んでいました。 ですがうまくいかず、時間だけが過ぎていたので質問した次第です。 (よくよく考えるとあれもソースに定義が書かれてた上、可変じゃなかったな…) >インプット・アウトプットともにただの文字列なんだから、そんなに難しく考えんでも…という感じです。 今回は使える範囲でライブラリの機能を使って、それ以外は文字列加工でやってしまおうと思います。
退会済みユーザー

退会済みユーザー

2019/06/16 03:58 編集

> 標準以外のライブラリを使うことは別に問題ないのですが、 > 他のライブラリを使用した方法を色々模索している余裕があまりないので、 > 今回は使える範囲でライブラリの機能を使って、 > あとは文字列加工で何とかするようにしてみます。 上のコメントで、 サードパーティ製のライブラリ MiniJSON でも、.NET 標準のライブラリの JavaScriptSerializer クラスのいずれを使っても Dictionary<string, object> 型にデシリアライズできます。シリアライズもできます。もちろん .NET 3.5 でも OK です。質問に書かれていた「←(増える可能性あり)」にも対応できます。 ・・・と書きましたが、読んでもらっているでしょうか? ピンと来てないようですので、後でそのサンプルを回答欄に書いておきます。
gentaro

2019/06/16 03:57

XMLを取り込む機能って、それは「XML文書そのもの」を扱っているという話じゃないんですか? XML(の表現で)シリアライズされたオブジェクトをJavaのオブジェクトにデシリアライズするのとは意味が異なると思いますが。(後者の話は今回の話と同じ問題が発生するはず)
YAmaGNZ

2019/06/16 04:12

Q71さんの回答じゃダメなんですか?
Q71

2019/06/16 14:11

今回の用途、メッセージリソースをツールの開発者以外が用意する、というのは、オンラインソフトウェアではよく見られるものです。「形・型が決まっていない」と見るか(こう見たのでdynamicを使う必要があり、4以降じゃないと無理だと思った)、「string,string という対の個数が決まっていない」と見るかで、設計に無理云々は変わると思います。DataGridViewに表示するものの個数なんて、設計時には不明なのですから。 おっと、フォームの個数も変わるって?コンボボックスで表示するマスタを切り替えるという話も、よくあることです。知っている形に落とし込めれば、簡単になります。
guest

回答5

0

質問に対しては全然あさっての話でしたなんですけど、ビジネス的に意味ある気がするのでかきますね。

多言語対応をしてるアプリで外注とかもしてるエンジニア側の取りまとめしてました。
翻訳てワードとか文字とかが課金単位です。これで外注すると、たとえばuseridで二重にお金かかります。
お金の問題ならまだましなんですが、それぞれ違った翻訳されることがあって、英語が共通ってわかってても検収のときにチェックされません。
さらに、ログインだけ改修したときにそこだけ翻訳に出します。変わってないのにお金払いたくないから。その翻訳戻りが未改修の既存部分と合致してるかなんて絶対にスルーされます。
そして、真面目なかたが見て直すと、今度は直すべきでないやつを直してしまいます。業務直結でない例だとうまいたとえがないのですが、waterをお湯と水に分けてるのを合わせちゃだめなんです。

意味ベースで単純なキーバリューにしたほうがいいと思います。翻訳は。翻訳はTSVでバージョン管理して、みるときはエクセル、がよいと思います。
そしてそのキーを画面にマップしたほうがいいと思います。ということで要件見直しては?

投稿2019/06/13 09:45

papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nonki03

2019/06/16 03:24

なるほど…翻訳作業を依頼する場合はそのようになるのですね… まだ開発で手一杯の駆け出しなので、そういったところに焦点を合わせたことがありませんでした。ご教授ありがとうございます。 以前の旧アプリのほうでは単純なキーバリューだったのですが、どこの画面の文言かわからないから~とのことで、今回のようなフォーマットになったそうです。 別の旧アプリのほうでは、[画面コード_キー,バリュー]といった形でCSVにて管理していたため、そういったところを踏まえて見直す気はないか相談を持ち掛けてみます。
guest

0

質問欄のやりとりを見て回答を変更します。

最終的にやりたいのは

  1. JSON形式のテキストファイルを読み込む
  2. 読み込んだデータは「画面名-項目名-現地語のテキスト」の形式として編集できるようにする
  3. JSON形式のテキストファイルとして書き出す

という話みたいなので、2の部分は

C#

1public class Entry { 2 pubilc string ViewName { get; set;} 3 pubilc string ItemName { get; set;} 4 pubilc string Text { get; set;} 5}

みたいなやつをList<Entry>みたいにリストに突っ込んで扱えれば十分だと思います。

問題は1と3ですが、これを無理やりJSONをデシリアライズ・シリアライズでやろうとしているあたりが苦労しているポイントだと思います。

Zuishinさんがコメントされていたとおり、JSONはただのテキストファイルです。
これを読み込んで、上記のクラスのインスタンスが作れたり、書き出せたりすれば十分なはずです。

例えば

C#

1public class JSonDataFileReader { 2 public IEnumerable<Entry> Load(string filename) { 3 var data = File.ReadAllText(filename); 4 var result = new List<Entry>(); 5 // ループ: dataの中身を正規表現を使って1画面分ずつマッチさせる 6 var viewname = // 画面名に該当する要素を正規表現で取り出す 7 // ループ: マッチさせた1画面分の文字列から、各要素ごとにマッチさせる 8 var obj = new Entry { 9 ViewName = viewName, 10 ItemName = // 項目名に該当する要素を正規表現で取り出す 11 Text = // テキストに該当する要素を正規表現で取り出す 12 }; 13 result.Add(obj); 14 15 return result; 16 } 17}

みたいな感じで読めますよね。(書き出す方は省略)

投稿2019/06/12 20:30

編集2019/06/14 08:52
gentaro

総合スコア8949

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nonki03

2019/06/16 03:05

やりたいことはまさしくそうです。 jsonの中身を取り込んでList型としてメモリに保持、画面で編集して編集後のデータを元のjsonと同じフォーマットで書き出す。これだけです。 標準のライブラリにも、その他別ライブラリにもjsonを読み込む機能は色々あるのに、正規表現でゴリゴリと切り取ってList型に放り込むのはどうなのかな…と思っていましたが、画面名やKeyの部分が可変であることから、今回の読み込みに関しては正規表現を使ってちゃちゃっと切り取って取り込んだほうがよさそうに思えてきました。
guest

0

混乱させてしまって申し訳ない。.NET Framework 3.5 で実行できます。
Visual Studio 2019 で、C#, Windows Form アプリケーション, .NET Framework 3.5 で作成したプロジェクト。実行環境に 「lang/en.json」が、 UTF-8 で保存されていることを前提。

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.IO; 7using System.Linq; 8using System.Text; 9using System.Windows.Forms; 10using Newtonsoft.Json; 11 12namespace teratail194657 13{ 14 public partial class Form1 : Form 15 { 16 public Form1() 17 { 18 InitializeComponent(); 19 var resource = LoadResources("en"); 20 } 21 22 private Dictionary<String, Dictionary<String, String>> LoadResources(String lang) 23 { 24 String filename = Path.Combine("lang", $"{lang}.json"); 25 var serializer = new JsonSerializer(); 26 using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) 27 using (var reader = new StreamReader(stream, Encoding.UTF8)) 28 using (var jreader = new JsonTextReader(reader)) 29 { 30 return serializer.Deserialize<Dictionary<String, Dictionary<String, String>>>(jreader); 31 } 32 } 33 } 34}

resource に、Dictionary<String, Dictionary<String, String>> の形式で入ってくるので、resource["LoginScreen"]["label_title"] のようにアクセスします。

追記
編集ツールでは、foreeach 句で KeyVakuePair<> にアクセスするなどしてください。

投稿2019/06/13 13:01

編集2019/06/14 02:17
Q71

総合スコア995

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/06/13 14:09 編集

> resource["LoginScreen"]["label_title"] のようにアクセスします。 画面やその中の項目は増える(減ることも?)そうですので、上記のようなコーディングはできないはずで、その対応が必要かと思います。
Q71

2019/06/14 00:22

対策?Dictionaryクラスの使い方次第だと思いますが?実際、「その対応」はしていますので。
退会済みユーザー

退会済みユーザー

2019/06/14 00:51 編集

> Dictionaryクラスの使い方次第だと思いますが? その使い方を書いておかれた方が親切だと思うのですが。 > resource["LoginScreen"]["label_title"] のようにアクセスします。 質問者さんの「ツール」にそのようなコーディングをしたとすると、画面やその項目が増えたり減ったりしたときに、書き直し&再ビルド&再配布しなくて済むような手段はあるのでしょうか? もし手段がなければ、そのようなことを書くのは不適切ではないでしょうか?
YAmaGNZ

2019/06/14 04:40

文字列指定出来るんだからstring変数で指定できるわけで、なんで再ビルドって話になる?
Q71

2019/06/14 04:52

使い方がイメージできていないのでしょう。 編集ツールと、その他ツールがある。 編集ツールは滅多に更新しないが、その他ツールは更新があり得る。 その他ツールを更新した時、編集ツールを更新なしに使用したい。
nonki03

2019/06/16 03:42

jsonの中身を取ってきてからどうこうするのではなく、 取ってくる段階でDictionary<String, Dictionary<String, String>>の形式に 納めてしまう感じですか…なるほど…試してみます。
guest

0

質問に対する 2019/06/16 12:57 の私のコメントで、「ピンと来てないようですので、後でそのサンプルを回答欄に書いておきます」と書きましたが、それを以下に書いておきます。

サードパーティ製のライブラリ MiniJSON と .NET 標準のライブラリの JavaScriptSerializer クラスを使ったサンプルです。

まず JSON 文字列ですが、質問のサンプルを使います。以下の通りです。質問に書かれていた「←(増える可能性あり)」は削除しましたが、構文に従って正しく追加・削除すればサンプルコードはそのままで対応できます。

{ "LoginScreen":{ "label_title":"Login Screen", "label_userId":"User ID", "label_password":"Password", "button_login":"LOGIN" }, "UserLIstScreen":{ "label_title":"User List", "label_userId":"User ID", "label_userName":"User Name", "label_userTell":"TEL", "label_phone":"Phone", "label_save":"Save" }, "SettingListScreen" :{ "label_title":"Setting", "label_storeName":"Store Name", "label_language":"Language", "button_save":"Save" } }

サンプルコードは以下の通りです。上の JSON 文字列をテキストファイル TextFile2.txt に格納し、それを読んできて C# のオブジェクトにデシリアライズし、その後 JSON 文字列にシリアライズしています(シリアライズできないと編集結果を反映した JSON 文字列のファイルが作成できないので意味がないはず)。コメントにありますが、コードの前半が MiniJSON 利用、後半が JavaScriptSerializer 利用です。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using MiniJSON; using System.IO; using System.Web.Script.Serialization; namespace ConsoleAppMiniJson { class Program { static void Main(string[] args) { string path2 = @"C:\Users...\TextFile2.txt"; string jsonText2 = ""; using (StreamReader sr = File.OpenText(path2)) { jsonText2 = sr.ReadToEnd(); } // MiniJSON 利用 Console.WriteLine("--- MiniJSON 利用 -------------------------"); var json2 = (Dictionary<string, object>)Json.Deserialize(jsonText2); foreach (KeyValuePair<string, object> kvp in json2) { Console.WriteLine("Key = {0}", kvp.Key); Dictionary<string, object> value = (Dictionary<string, object>)kvp.Value; foreach (KeyValuePair<string, object> kvp2 in value) { Console.WriteLine(" Key = {0}, Value = {1}", kvp2.Key, (string)kvp2.Value); } } Console.WriteLine("----------------------"); var json2String = Json.Serialize(json2); Console.WriteLine(json2String); // JavaScriptSerializer 利用 Console.WriteLine("--- JavaScriptSerializer 利用 -------------"); JavaScriptSerializer serializer = new JavaScriptSerializer(); var json4 = serializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(jsonText2); foreach (KeyValuePair<string, Dictionary<string, string>> kvp in json4) { Console.WriteLine("Key = {0}", kvp.Key); Dictionary<string, string> value = kvp.Value; foreach (KeyValuePair<string, string> kvp2 in value) { Console.WriteLine(" Key = {0}, Value = {1}", kvp2.Key, kvp2.Value); } } Console.WriteLine("----------------------"); var json4String = serializer.Serialize(json4); Console.WriteLine(json4String); } } }

上のコードを、Windows 10 Pro 64-bit 上の VS2008 Pro で、.NET 3.5, プラットフォームターゲット AnyCPU に設定してコンパイル/実行し、以下の結果が得られます。

イメージ説明

見ての通り、デシリアライズした C# の Dictionary 型のオブジェクトから foreach ループを回して全ての key と value が取得できています。

取得した key と value を、質問者さんが作るという「ツール」のエディタに取り込んで編集し、編集結果から同様な C# の Dictionary 型のオブジェクトを作り、シリアライズするということを検討するということになると思います。

投稿2019/06/16 04:40

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

このJSONを使用するアプリ側でも読み込みロジックが実装されていないのですか?
読み込みロジックはそこから持ってくればいいと思います。
そのアプリで読み込んだデータを格納するための構造体なりクラスなりがあると思うのですが、それをシリアライズ(デシリアライズ)すればいいのではないですか?

投稿2019/06/12 15:23

YAmaGNZ

総合スコア10242

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nonki03

2019/06/16 02:53

アプリ側は他社さんの開発になっていて、未だサンプル画面程度しかできていません。 サンプル画面ゆえに直値でやってそうですから、おそらくまだ読み込みロジックは無いのではないか…と思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問