1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C#でjsonを読み込み・そして辞書型に変換(強引)

Last updated at Posted at 2020-11-13

お久しぶりです。

Qiitaの皆さん、お久しぶりです。
前回からかなり時間が空きすぎましたが、あれから念願の新しいパソコンを購入しました。
そしてPythonにも飽きてきたので、C#に手を出してみることにしました。

理解するメモとして書き残しておきます。
ガバな点はご容赦ください。

ふと思ったjsonの読み込みについて

私は以前、Pythonでjsonを使用して設定ファイルやデータをイチイチに定義しなければならないものをjsonに格納して便利に使っていたので、ぜひC#でも使いたいと思い模索しました。
薄々気づいてはいましたが、Pythonはなんて素晴らしいライブラリを取り揃えているのかと思い知らされることになりました。

json読み込みのコード

hoge.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());

        }
    }
}

...自分でも感じた、強引すぎると...

問題点

  1. valueがint型だろうとなんだろうとstring型にしてresult(辞書型)に格納する。
  2. 結局jsonデータのクラスを指定しなければならないので、根本的な解決には至っていない。
  3. とりあえず思いついた発想と知恵で強引に作ったので、見られたら怒られるくらいのガバコード

個人的にはPythonのように使えるのが一番ありがたいですが、あまりに強引すぎて怒られるような気がします。

ちなみに結果は

hoge1
hoge2
hoge3
System.String
System.String
System.String

こんなふうに表示されます。

最後に

この方法より「こうしたほうがいいよ~・ガバすぎこれを使え」等あれば、ご遠慮無くぜひコメントまで!
結構真剣に困っていたので、また時間があれば改良してみます。

追記
これなんなんですかね?よく出てきて動かなくなります。
こうなるともう保存して起動し直すしかないのでめっちゃ不便です。Screenshot_11.png

久々に書き切りました。
おやすみなさい。

引用元

https://usefuledge.com/csharp-json.html
https://json2csharp.com/ (先程のjsonデータクラスをjsonデータをもとに作ってくれるサイト、めっちゃ便利)
Thank you!!!!!

1
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?