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

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

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

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

JSON

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

Q&A

解決済

3回答

6159閲覧

C#でJSONデータの型を変換する

Sanm

総合スコア10

C#

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

JSON

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

0グッド

2クリップ

投稿2019/08/07 15:19

編集2019/08/07 23:01

前提・実現したいこと

まず、a.jsonファイルを読み込み、データ内の"dataname"を見る。
b.JSONファイルの"dataname"を参照し、a.jsonファイルの"dataname"と一致したら"type"を見る。
そのtypeによって、a.jsonファイル内の"value"のデータの型を変換し、output.jsonファイルで出力する。
を実装したいです。

該当のソースコード

//a.json { "data": [ { "id": "100_1", "name": "tarou", "dataname": "AAA", "value": 155 }, { "id": "100_2", "name": "hanako", "dataname": "BBB", "value": 50 }, { "id": "100_3", "name": "manami", "dataname": "AAA", "value": 120 } ] }
//b.json { "definition": [ { "dataname": "AAA", "type": "string" }, { "dataname": "BBB", "type": "float" }, { "dataname": "CCC", "type": "int" } ] }

結果は
id:100_1 の value:"155"
id:100_1 の value:50.0
id:100_1 の value:"120" となるはずなので、

//output.json { "data": [ { "id": "100_1", "name": "tarou", "dataname": "AAA", "value": "155" }, { "id": "100_2", "name": "hanako", "dataname": "BBB", "value": 50.0 }, { "id": "100_3", "name": "manami", "dataname": "AAA", "value": "120" } ] }

試したこと

色々なサイトを巡り、以下までコーディングができましたが、これ以上手が進まなくなってしまいました…
お目汚しで申し訳ありません。(VisualStudio2019でjson.NET,C#を用いてコーディングしています)

using Newtonsoft.Json; using System; using System.IO; using System.Text; namespace ConsoleApp_1 { class Program { static void Main(string[] args) { string filepath = @"C:\Users\User\Desktop\a.json"; string jsonstring = File.ReadAllText(filepath, Encoding.UTF8); Console.WriteLine("読込完了"); var obj = JsonConvert.DeserializeObject(jsonstring); var deserialized = JsonConvert.DeserializeObject<object>(jsonstring); Console.WriteLine(deserialized); File.WriteAllText(@"C:\Users\User\Desktop\output.json", deserialized.ToString()); Console.WriteLine("出力完了"); } } }

皆様のお力添えをよろしくお願いいたします。

失礼しました。編集しました。
そうです。違う型で出力したいです。
ただ、そのやり方が見当つかず苦戦しています。
output.jsonの不備はどこか分かりませんでした。

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

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

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

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

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

gentaro

2019/08/07 16:42

> 具体的にソースコードを記載いただけますと幸いです。 丸投げ依頼にみえるんでどうかと思いますが。 とりあえず気になるのが、 value を文字列だったり数値型だったり混在させて出力したいということですか?
退会済みユーザー

退会済みユーザー

2019/08/07 22:41

質問にある output.json は JSON として不正 (なので、デシリアライズ出来ない、使えない) のように見えます。違ったら失礼。でも、もしそうなら、全体的に見直した方が良さそうです。
YAmaGNZ

2019/08/07 22:52 編集

output.jsonはjson2csharpでコード化出来ましたよ。 というか、ajsonのvalueをobjectとしただけではないでしょうか?
Zuishin

2019/08/07 23:07

「この関数を使うよ」というほどのものではなく、ループ内で swich や if を使うだけでできますね。 「これ以上手が進まなくなりました」のコード内には Json のデコード以外何も書かれていないので、ほんとうにこれしかできないのであれば、何も作れないと思います。 完成を目指すなら場当たり的に勘でコピペするのではなく、まず文法を確認してください。ループも分岐も使えずプログラミングしようというのは無謀すぎます。
退会済みユーザー

退会済みユーザー

2019/08/07 23:35

> output.jsonはjson2csharpでコード化出来ましたよ。 やってみました。value は object 型になりますね。「output.json は JSON として不正」とまでは言えなかったようです。 失礼しました>質問者さん でも、それからシリアライズした JSON 文字列をデシリアライズした時に、デシリアライズする処理系で value の型が判定できるのか悩ましそうです。やっぱり全面的に見直した方がよさそうな気はします。
guest

回答3

0

ベストアンサー

コード書いてみました。
"string" → typeof(string)
"float" → typeof(float)
"int" → typeof(int)
の変換には Dictionary を使いましたが、ここがもう少しスマートにできるとカッコいいかなと思います。

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.IO; 5using System.Text; 6using Newtonsoft.Json; 7 8namespace ConsoleApp8 9{ 10 class Program 11 { 12 static void Main(string[] args) { 13 var typeDic = new Dictionary<string, Type>(); 14 typeDic.Add("string", typeof(string)); 15 typeDic.Add("float", typeof(float)); 16 typeDic.Add("int", typeof(int)); 17 18 var rootA = GetJson<RootData>("a.json"); 19 var rootB = GetJson<RootDefinition>("b.json"); 20 foreach (var itemA in rootA.data) { 21 var itemB = rootB.definition.Find(data => data.dataname == itemA.dataname); 22 if (itemB != null && itemA.value != null) { 23 var cnv = TypeDescriptor.GetConverter(itemA.value.GetType()); 24 if (cnv != null) { 25 itemA.value = cnv.ConvertTo(itemA.value, typeDic[itemB.type]); 26 } 27 } 28 } 29 var outputString = JsonConvert.SerializeObject(rootA, Formatting.Indented); 30 File.WriteAllText("output.json", outputString, Encoding.UTF8); 31 Console.WriteLine(outputString); 32 Console.ReadKey(); 33 } 34 35 static T GetJson<T>(string filepath) { 36 string jsonstring = File.ReadAllText(filepath, Encoding.UTF8); 37 return JsonConvert.DeserializeObject<T>(jsonstring); 38 } 39 40 } 41 42 public class Data 43 { 44 public string id { get; set; } 45 public string name { get; set; } 46 public string dataname { get; set; } 47 public object value { get; set; } 48 } 49 50 public class Definition 51 { 52 public string dataname { get; set; } 53 public string type { get; set; } 54 } 55 56 public class RootData 57 { 58 public List<Data> data; 59 } 60 61 public class RootDefinition 62 { 63 public List<Definition> definition { get; set; } 64 } 65}

投稿2019/08/08 03:38

編集2019/08/08 03:42
KOZ6.0

総合スコア2626

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

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

Sanm

2019/08/08 05:22

お忙しい中コーディング、記載していただきありがとうございます。 現在私が作成しているものより断然見やすく、美しいです… 私の知らない技が多く感動します。 実際に動かしてみます。ありがとうございます。 1点、floatの型を追加したい場合はb.jsonデータ追加•typeDicに追加ですれば良いですか?
KOZ6.0

2019/08/08 05:38 編集

そうですね、それで OK です。
Sanm

2019/08/09 05:06 編集

ありがとうございます。 また、挙動の確認が取れました。 stringからstringへ変換する場合、エラーとなってしまいました。こちらに関して解決に至らない場合は後日別で質問しようと思います。
KOZ6.0

2019/08/10 06:36 編集

変ですね。 元の型が string なら TypeDescriptor.GetConverter は StringConverter を返すはずで、ConvertTo(value, typeof(string)) を実行してもエラーにはならないはずです。 ちょっとやってみましたがエラーにはなりませんでした。 新しい質問が上がっていないようなので解決したのであれば良いですが・・・
Sanm

2019/08/10 14:45

KOZ6.0様 気にかけていただきありがとうござます。 結果から申しますと、当方のオペレーションミスでした。 stringからstringへ正常に変換されることの確認ができました。 大変失礼いたしました。
guest

0

上の質問に対する私のコメントで、

デシリアライズする処理系で value の型が判定できるのか悩ましそうです。やっぱり全面的に見直した方がよさそうな気はします。

と書きました。

その対応ための代案ですが・・・

output.json を何かの処理系に渡しで、最終的にそこでデシリアライズして使うのだと思いますが、であれば、output.json は a.json と b.json をマージするような形、即ち以下のようにするという案は NG ですか?

{ "data": [ { "id": "100_1", "name": "tarou", "dataname": "AAA", "value": 155, "type": "string" }, { "id": "100_2", "name": "hanako", "dataname": "BBB", "value": 50, "type": "float" }, { "id": "100_3", "name": "manami", "dataname": "AAA", "value": 120, "type": "string" } ] }

投稿2019/08/07 23:46

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Sanm

2019/08/08 00:06

代替案のご提示ありがとうございます。 参考にさせていただきます。 javascript で別の方が書いたコードをC#化しているので、頂いた案が可能かは分かりませんが、打診してみます。 ありがとうございます。
退会済みユーザー

退会済みユーザー

2019/08/08 00:31

全体的なやりたいことのシナリオ・ストーリーを書いてください。初心者の方は特に。 XY問題の Y の質問をしているとすると、それに対する回答をしても、X の解決にはつながりにくいので。 (XY問題とはなにか不明でしたらググってください。そういう質問をする人がここにも結構多いようです)
YAmaGNZ

2019/08/08 00:49

javascriptの移植ということであれば、output.jsonのフォーマットも現状仕様となっているのでしょうから変更は難しいのではないでしょうか? XY問題とはまた違った形のように思えます。
退会済みユーザー

退会済みユーザー

2019/08/08 01:51

それは自分は質問からは読めないです。 既存のアプリがあって、それは質問者さんの output.json の形式でなければならないということか、a.json と b.json 形式は決まっているがそれ以外 output.json の形式や C# での処理方法などはこれから質問者さんが考えて決めるのか、なにも決まってないからゼロから検討中で取り敢えず質問に書いてある案を考えてみたのか・・・
YAmaGNZ

2019/08/08 01:56

質問からは読めませんが、コメントに「javascript で別の方が書いたコードをC#化している」とありますから、既存の何かがあると考えられると思いますが・・・
退会済みユーザー

退会済みユーザー

2019/08/08 02:06

想像で話をしても何ですので、質問者さんからの回答を待ちたいと思います。
Sanm

2019/08/08 05:16

皆さまらご検討していただきありがとうございます。 こちらはC#での処理方法以外の部分は決められています。 打診しましたが現行のフォーマットを崩すのはあまり推奨しないとの事でした。
guest

0

  1. a.jsonをデシリアライズする
  2. b.jsonをデシリアライズする
  3. a.jsonの項目数分以下の処理を続ける

  3-1. b.jsonの項目からdatanameが同じものを見つける
3-2. 見つかった場合、typeによってa.jsonのvalueをキャストする
0. 変換の終わったa.jsonをoutput.jsonとしてシリアライズして書き込む

このような流れになるかと思います。
1.や2.が出来ているかは、その内容を一覧で表示してみるとよろしいかと思います。
3.についてはC#の基本的な構文で実現できるはずです。

また、1.2.4.については検索すればいくらでも例が出てくると思います。
読み込むべき型を定義するのが分かりやすくなるのではないかと思います。
JSONの型定義であれば、json2csharpみたいな便利なサイトがいくつかあります。

投稿2019/08/07 23:10

YAmaGNZ

総合スコア10242

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

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

Sanm

2019/08/08 00:04

頭の中を整理して頂いたかのようなご丁寧な回答ありがとうございます。 1,2,4は出来そうな気がします。 そうなると3はswitchかforかifを使うのでしょうか? また、それぞれはobject化した方が良いですか?
YAmaGNZ

2019/08/08 00:24

3の処理へ繋げるためにも、1や2の結果を一覧で表示するということを薦めています。 一覧で表示するということは、全てのデータを見ることになりますので、必然的に3の実装に近いものになります。 >また、それぞれはobject化した方が良いですか? それぞれとは何を指しますか?object化とはどのような意味合いですか?
Sanm

2019/08/08 05:16 編集

1,2は完了、3は作業中です。 コードを載せることができず申し訳ありません。 表現が良くなかったです。a,b両ファイルRead後、JObject使用しますか?という意味でした。
YAmaGNZ

2019/08/08 05:20

JObjectを使用してもいいでしょうが、KOZ6.0さんのようにデータを格納するクラスを定義したほうが、コードも分かりやすくなるかと思います。
Sanm

2019/08/08 05:27

KOZ6.0様のコードを見て当方もそう思いました… YAmaGNZ様、色々とご教授いただきありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問