お久しぶりです。
Qiitaの皆さん、お久しぶりです。
前回からかなり時間が空きすぎましたが、あれから念願の新しいパソコンを購入しました。
そしてPythonにも飽きてきたので、C#に手を出してみることにしました。
理解するメモとして書き残しておきます。
ガバな点はご容赦ください。
ふと思ったjsonの読み込みについて
私は以前、Pythonでjsonを使用して設定ファイルやデータをイチイチに定義しなければならないものをjsonに格納して便利に使っていたので、ぜひC#でも使いたいと思い模索しました。
薄々気づいてはいましたが、Pythonはなんて素晴らしいライブラリを取り揃えているのかと思い知らされることになりました。
json読み込みのコード
{
"hoge": "hoge1",
"hogehoge": "hoge2",
"hogehogehoge": "hoge3"
}
Pythonでのjsonの読み込みはjsonライブラリを使用しますが
import json
def load_json(filename):
with open(filename) as files:
load = json.load(files)
return load
このように関数を一つ定義してしまえば、辞書型で帰ってくるので
result = load_json("hoge.json")
hoge1 = result["hoge"]
hoge2 = result["hogehoge"]
hoge3 = result["hogehogehoge"]
print(hoge1)
print(hoge2)
print(hoge3)
print(type(hoge1))
print(type(hoge2))
print(type(hoge3))
hoge1
hoge2
hoge3
<class 'str'>
<class 'str'>
<class 'str'>
こうすると簡単にstrやintで帰ってきますので、あとは煮るなり焼くなりすれば簡単に使うことができますが
(ガバコードデゴメンネ)
C#の場合
using System;
using System.IO;
using System.Text;
using System.Text.Json;
namespace ConsoleApp2
{
class Program
{
public static string ReadAllLine(string filePath, string encodingName)
{
StreamReader sr = new StreamReader(filePath, Encoding.GetEncoding(encodingName));
string allLine = sr.ReadToEnd();
sr.Close();
return allLine;
}
class hogejson
{
public string hoge { get; set; }
public string hogehoge { get; set; }
public string hogehogehoge { get; set; }
}
static void Main(string[] args)
{
string readjson = ReadAllLine("hoge.json", "utf-8");
hogejson jsonData = JsonSerializer.Deserialize<hogejson>(readjson);
string hoge = jsonData.hoge;
string hogehoge = jsonData.hogehoge;
string hogehogehoge = jsonData.hogehogehoge;
Console.WriteLine(hoge);
Console.WriteLine(hogehoge);
Console.WriteLine(hogehogehoge);
Console.WriteLine(hoge.GetType());
Console.WriteLine(hogehoge.GetType());
Console.WriteLine(hogehogehoge.GetType());
}
}
}
hoge1
hoge2
hoge3
System.String
System.String
System.String
こんな感じで記載しないとうまく読み込まないのですが、一番個人的に面倒なのが
「jsonのクラスを作らないといけない」
のと
「メソッド(Pythonでいう関数(若干違うけど))作った時わかりにくい!
ことが引っかかりました。
なぜこんなことになってしまったのか
Pythonは先程の関数で帰ってくる返り値は辞書型に対してC#は特定の返り値を指定しなければなりません。
このため、Pythonでは辞書型で帰ってくるので
hoge = result["hoge"]
とresultに指定定するだけでkeyである「hoge」のvalue「hoge1」を取り出すことができますが
対してC#は、例えば「hoge.json」のkeyである「hoge」のvalueが「hoge1」であったとき、クラス「hogejson」のhogeにstring型(str)でセットされます。
逆にこれをint型や別の型でセットしようとしてもできません。
なぜなら、クラスhogeの返り値はstringと決めているからです。
そのためPythonでよくお世話になった辞書型に返り値には指定されていないため、仮に返り値を"勝手"に辞書型に指定しても他の「hogehoge」や「hogehogehoge」のkeyはおろかvalueの情報すらありません(自己解釈)
ほんじゃあ辞書型に返ってくるように作ろう!笑
探してみたところ、C#には「Dictionaryクラス」というものが存在するようで、それでPythonの辞書型と同じように使えるみたいです。
なら話は早いです、hoge.jsonのkeyとvalueを辞書型に詰め込めるよう試行錯誤を繰り返してできたのがこちらです。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
namespace ConsoleApp2
{
class library
{
// ファイル読み込み
public string ReadAllLine(string filePath, string encodingName)
{
StreamReader sr = new StreamReader(filePath, Encoding.GetEncoding(encodingName));
string allLine = sr.ReadToEnd();
sr.Close();
return allLine;
}
// List型をDictionary型に強引に変換する
public static Dictionary<string, string> ListInDictionary(string[] left, string[] right)
{
// 一致したとき
if (left.Length == right.Length)
{
var result = new Dictionary<string, string>();
// leftのListの数の分だけforを回す
for (int i = 0; i < left.Length; i++)
{
// resultに辞書を追加
result.Add(left[i], right[i]);
}
return result;
}
// 不一致のとき
else
{
return null;
}
}
class hogejson
{
public string hoge { get; set; }
public string hogehoge { get; set; }
public string hogehogehoge { get; set; }
}
//hoge.jsonを読み込むためのメソッド
public Dictionary<string, string> GetHogejson(string filename)
{
try
{
string jsonfile = ReadAllLine(filename, "utf-8");
hogejson jsonData = JsonSerializer.Deserialize<hogejson>(jsonfile);
string[] json_key = { "hoge", "hogehoge", "hogehogehoge" };
string[] json_value = { jsonData.hoge, jsonData.hogehoge, jsonData.hogehogehoge };
var result = ListInDictionary(json_key, json_value);
return result;
}
// jsonが読み込めない時
catch (JsonException)
{
return null;
}
}
}
class Program
{
static void Main(string[] args)
{
library Library = new library();
Dictionary<string, string> gethogejson = Library.GetHogejson("hoge.json");
string hoge, hogehoge, hogehogehoge;
hoge = gethogejson["hoge"];
hogehoge = gethogejson["hogehoge"];
hogehogehoge = gethogejson["hogehogehoge"];
Console.WriteLine(hoge);
Console.WriteLine(hogehoge);
Console.WriteLine(hogehogehoge);
Console.WriteLine(hoge.GetType());
Console.WriteLine(hogehoge.GetType());
Console.WriteLine(hogehogehoge.GetType());
}
}
}
...自分でも感じた、強引すぎると...
問題点
- valueがint型だろうとなんだろうとstring型にしてresult(辞書型)に格納する。
- 結局jsonデータのクラスを指定しなければならないので、根本的な解決には至っていない。
- とりあえず思いついた発想と知恵で強引に作ったので、見られたら怒られるくらいのガバコード
個人的にはPythonのように使えるのが一番ありがたいですが、あまりに強引すぎて怒られるような気がします。
ちなみに結果は
hoge1
hoge2
hoge3
System.String
System.String
System.String
こんなふうに表示されます。
最後に
この方法より「こうしたほうがいいよ~・ガバすぎこれを使え」等あれば、ご遠慮無くぜひコメントまで!
結構真剣に困っていたので、また時間があれば改良してみます。
追記
これなんなんですかね?よく出てきて動かなくなります。
こうなるともう保存して起動し直すしかないのでめっちゃ不便です。
久々に書き切りました。
おやすみなさい。
引用元
https://usefuledge.com/csharp-json.html
https://json2csharp.com/ (先程のjsonデータクラスをjsonデータをもとに作ってくれるサイト、めっちゃ便利)
Thank you!!!!!