【C#】JSONファイルを読み込む

JSONファイル読み込みを行うことになったのでやり方をメモ。

1. JSONファイルの読み込み

まずはjsonファイルのパスを指定して内容を読み込みます。jsonldファイルもいけます。

string FilePath = @"hoge/huga.json"; //ファイルパス
var json = File.ReadAllText(FilePath); // ファイル内容をjson変数に格納

jsonを読み込むにはメモリストリームが必要です。メモリストリームはデータの読み込みをバイト単位で行えます。 エンコードはUTF8で行います。

var ms = new MemoryStream(Encoding.UTF8.GetBytes((json)));

2. jsonデータの格納

また、jsonにはKeyとValueといった具合にデータが記述されていますので、これを取り出してValueを変数に格納したいところです。 jsonのKeyを取得するにはデータコントラクト属性を用います。

データコントラクト属性はもともとXmlファイルのデータをシリアル化するものでしたが、jsonにも対応しています。シリアライズ(書き込み)とデシリアライズ(読み込み)ができます。

例えば、jsonファイルの "id" 属性を取得したい場合はデータコントラクト属性のクラスを作成し、データメンバ属性でメンバ変数を宣言します。データメンバの Name に取得したいjsonのKeyを入れると、その値が取得できます。ただし、Key名が正しくないと取得できないので注意が必要です。Valueも型を合わせます。

[DataContract] //データコントラクト属性
public partial class JsonData
{
    [DataMember(Name = "id")] //データメンバ属性
    public int Value { get; set; }
}

このようにしてjsonから取得したいデータをデータコントラクトになげて、そのデータをメンバ変数で管理します。

3. JSONファイルのデータ格納

jsonファイルの読み込みは先頭ビットから読み込みたいので、ストリームの位置を先頭にします。読み込み次第、そのデータを変数に格納したいので、as演算子で変数を宣言したクラスに変換します。

ms.Seek(0, SeekOrigin.Begin); // ストリームの先頭
var data = serializer.ReadObject(ms) as JsonData; //データをJsonDataクラスに変換

あとはデータが正しく入力されているかを確認するだけです。

Console.WriteLine($"ID : {data.Value}");

4. 試した結果

私が読み込みたいのはちょっと複雑なjsonでしたので、いくつかクラスを作って試してみました。 読み込むjsonファイルはこちらです。人狼ゲームのデータです。

github.com

ちなみに、このjsonファイル、配列の中に構造体が入っているような複雑なファイルです。なので、クラスの中にクラスをいれることで配列の中に構造体を格納するようなデータ構造にします。

例えば、morning.jsonldファイルの67行目からcharacter配列の中には"@id"や"@context"などが入っていますが、72行目"name"が構造体になっています。なので、クラス1つだけではデータを正しく受け取れません。このままプログラムを実行すると例外 (item要素が~的な例外) が発生します。

そこで、characterクラスの中にnameクラスを作成すれば解決です。jsonのname構造体にはjaとenのKeyが含まれているので、これらを宣言します。

[DataContract]
public partial class Character
{
    [DataMember(Name = "name")]
    public Name Name { get; set; } //Nameクラスを参照
}

[DataContract]
public partial class Name //Nameクラス
{
    [DataMember(Name = "en")]
    public string En { get; set; }

    [DataMember(Name = "ja")]
    public string Ja { get; set; }
}

これで配列の中にある構造体データを格納できます。これに合わせれば、配列の中に配列や構造体の中に構造体といった、複雑なデータ構造を扱えます。名付けて ”クラスの中にクラス大作戦” とかですかね...。

これを用いて、実際にやってみました。

string FilePath = @"C:\werewolfworld-gh-pages\village\example\0.3\server2client\morning.jsonld";
var serializer = new DataContractJsonSerializer(typeof(JsonData));
var json = File.ReadAllText(FilePath);
var ms = new MemoryStream(Encoding.UTF8.GetBytes((json)));
ms.Seek(0, SeekOrigin.Begin);
var data = serializer.ReadObject(ms) as JsonData;

for (int i = 0; i < data.Context.GetLength(0); i++)
Console.WriteLine($"context{i} : {data.Context[i].ToString()}");

Console.WriteLine($"Token : {data.Token}");
Console.WriteLine($"Phase : {data.Phase}");
Console.WriteLine($"Date : {data.Date}");
Console.WriteLine($"PhaseTimeLimit : {data.PhaseTimeLimit}");
Console.WriteLine($"ServerTimestamp : {data.ServerTimestamp}");
Console.WriteLine($"ClientTimestamp : {data.ClientTimestamp}");

for(int i = 0; i<data.Character.GetLength(0); i++) //キャラクター情報の表示
{
    Console.Write($"参加者ID {data.Character[i].CharacterId} : "); //プレイヤーID
    Console.Write($"{data.Character[i].Name.Ja} ({data.Character[i].Name.En})"); // プレイヤー名
    Status = data.Character[i].Status;
    if(Status == "alive")
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($" {data.Character[i].Status}");
        Console.ForegroundColor = ConsoleColor.White;
    }
    else if(Status == "dead")
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.ForegroundColor = ConsoleColor.White;
    }
                
}

JsonDataクラスはこんな感じです

[DataContract]
public class JsonData
{
    [DataMember(Name = "@context")]
    public string[] Context { get; set; }

    [DataMember(Name = "@id")]
    public string Id { get; set; }

    [DataMember(Name = "token")]
    public string Token { get; set; }

    [DataMember(Name = "phase")]
    public string Phase { get; set; }

    [DataMember(Name = "date")]
    public int Date { get; set; }

    [DataMember(Name = "phaseTimeLimit")]
    public int PhaseTimeLimit { get; set; }

    [DataMember(Name = "serverTimestamp")]
    public string ServerTimestamp { get; set; }

    [DataMember(Name = "clientTimestamp")]
    public string ClientTimestamp { get; set; }

    [DataMember(Name = "character")]
    public Character[] Character { get; set; }
}

[DataContract]
public partial class Character
{
    [DataMember(Name = "@context")]
    public Uri Context { get; set; }

    [DataMember(Name = "@id")]
    public Uri Id { get; set; }

    [DataMember(Name = "isMine")]
    public bool IsMine { get; set; }

    [DataMember(Name = "name")]
    public Name Name { get; set; }

    [DataMember(Name = "image")]
    public Uri Image { get; set; }

    [DataMember(Name = "id")]
    public int CharacterId { get; set; }

    [DataMember(Name = "status")]
    public string Status { get; set; }

    [DataMember(Name = "update")]
    public Update Update { get; set; }

    [DataMember(Name = "isAChoice")]
    public bool IsAChoice { get; set; }
}

[DataContract]
public partial class Name
{
    [DataMember(Name = "en")]
    public string En { get; set; }

    [DataMember(Name = "ja")]
    public string Ja { get; set; }
}

[DataContract]
public partial class Update
{
    [DataMember(Name = "@id")]
    public Uri Id { get; set; }

    [DataMember(Name = "phase")]
    public string Phase { get; set; }

    [DataMember(Name = "date")]
    public long Date { get; set; }
}

これで動かしてみます。

f:id:takunology:20191113000648p:plain

構造体の中身が表示されています。

今回作成したコード

参考にどうぞ。

github.com

参考サイト

参考にしたサイトです。ありがとうございます。

シリアライズ

blog.okazuki.jp

データコントラクト

docs.microsoft.com

【C#】Visual Studio Online がアツい件

【朗報】VSCodeがオンラインで使えるだとっ!?

ついに、ついに、ついに!!
VSCodeがオンラインで利用できるようになりました!
何が嬉しいかというと、Web上でプログラミングができるのです。

「それだけ?」という人、いやいやちょっと待ってください。Web上ですよ?

プラットフォームに依存なくプログラムが書けるので、どんな端末でも同じような環境でプログラミングできます。素晴らしい!

Visual Studio Onlineを使うための準備

サイトへアクセス

マイクロソフトアカウントが必要なので、サインアップします。 visualstudio.microsoft.com

f:id:takunology:20191106190331p:plain

Azureへの登録

どうやらVisual Studio Onlineを使用するにはAzureへの登録が必要みたいです。

f:id:takunology:20191106191302j:plain

もし登録していない人がいればAzureに登録しましょう。私は学生なので、Azure for Studentsを利用しています。学生の方は無料で100ドル分使用できます。

azure.microsoft.com

サブスクリプションの登録

Azureに登録できていると、有効なサブスクリプションが表示されています。あとは好きにオプションを選んで作成します。

f:id:takunology:20191106192341p:plain

仮想マシンの作成

VS Onlineは仮想マシン上でVS Codeを動かしています。そのためのマシンを作成します。

私は4コア8GBメモリのマシンを作成しました。

f:id:takunology:20191106193004p:plain

f:id:takunology:20191106193224p:plain

これでマシンが作成できました。

実際に使ってみる

作成後は起動状態になっています。これをクリックすると、VSCodeと同じような画面に遷移します。

f:id:takunology:20191106194429j:plain

ただ、このままでは読み取り専用のコマンドで入力ができません。

メニューから新しいターミナルを開きます。

f:id:takunology:20191106201330p:plain

Linuxと同じようにコマンドを使用できます。

f:id:takunology:20191106201408p:plain

gccdotnet 系のコンパイラやサービスが最初から入っているので、すぐにでもプログラミングできます。

.NET Core の更新がてら .NET Core 3.0 をインストールしました。

.NET Core 3.0 のインストール

インストール方法はこのサイトの、Debian9 Linux を参考にコマンドをたたいてみましょう。

dotnet.microsoft.com

f:id:takunology:20191106202129p:plain

f:id:takunology:20191106202615p:plain

一度、仮想マシンサスペンドにして再起動してみます。

f:id:takunology:20191106203212p:plain

はい、3.0 入りました。

何ができるかはコマンドで調べられます。

$ dotnet new --list

いろんなものが作れますね!

f:id:takunology:20191106203708p:plain

.NET Core でコンソールアプリを作る

早速コンソールアプリを作ってみます。

$ dotnet new console --name Hello

これで Hello というディレクトリの中に Program.cs ができます。ここにプログラムを書いていきます。

using System;

namespace Hello
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, Takunology!");
        }
    }
}

これで実行できます。

f:id:takunology:20191106205516p:plain

iPadiPhone でプログラミング

サインアップしたあと、仮想マシンに接続すれば上記と同じように使用できます。

iPadで実行してみるとこんな感じです。実行しているのは前回のブログに書いた3層ニューラルネットワークです。

f:id:takunology:20191106210709p:plain

iPhone で動かしている様子です。が、アイコンが電話とビールになっています(爆笑)

f:id:takunology:20191106210941p:plain

2019年11月6日現在、キーボードでエンターをタップすると、キー入力モードが解除されてしまうので改行できません。プログラミングしづらいです。

なので、Bluetoothキーボードを買うのをおススメします。

おわりに

皆さんも良きプログラミングライフを!

f:id:takunology:20191106211222j:plain

参考

.NET Core 3.0 のインストールで参考にさせていただきました。

ありがとうございます。

blog.okazuki.jp

【C#】深層学習入門 #5 ニューラルネットワークの実装1

はじめに

前回までに行列のロジックをやったので、今回はニューラルネットワークを実装してみます。まだニューラルネットワークの学習や出力層を調整する関数は考慮していません。フォワード方向のみです。

ニューラルネットワークの実装1

Github

github.com

【C#】深層学習入門 #4 3層ニューラルネットワークと行列計算

はじめに

ニューラルネットワークは活性化関数を用いて、中間層をもつものです。しかし、具体的にどのようなロジックで解を導き出すのかがわかりません。今回は行列計算からはじまり、ニューラルネットワークのロジックに迫ります。

3層ニューラルネットワークと行列計算

Github

github.com

【C#】深層学習入門 #3 ニューラルネットワークと活性化関数

はじめに

多層パーセプトロンは単層パーセプトロンを複数の層で重ねたものであり、ニューラルネットワークとも言えます。が、活性化関数があるかないかでニューラルネットワークかどうかが決まります。とくに最近ではReLU関数を活性化関数として扱っているものをニューラルネットワークと呼ぶようです。

ニューラルネットワークと活性化関数

WPFでのグラフ作成

グラフの作成方法はこれを参考にしてください。

blog.takunology.jp

Github

github.com

【C#】深層学習入門 #2 多層パーセプトロン

はじめに

前回は単層パーセプトロンについてやりました。単純な論理回路(AND, OR, NAND) は実装できましたが、このままでは組み合わせ回路が実現できません。特にXORはNANDとORで作りますが、単層ではNANDもしくはORのどちらかしか実装できません。なので、層を増やして多層パーセプトロンを使い、組み合わせ回路を作りましょうという内容です。

多層パーセプトロン

Github

github.com

【C#】深層学習入門 #1 単層パーセプトロン

はじめに

最近話題の機械学習。その中でも深層学習を扱うところが多いですね。ゲームAIをはじめ、画像認識やセキュリティなど幅広く活躍しています。 自分も興味があったのですが、アルゴリズムが苦手で敬遠していました。しかし、やっぱり機械学習やってみたいと興味を持ち始めたので本を参考にしながらやっていこうと思います。

参考文献

こちらの本を読みながら、アウトプットがてら記事に書いていこうと思います。

www.oreilly.co.jp

が、このままだとただの写経になるので、いろいろ工夫しながらブログに書いていきます。ちなみに、この本はPythonで実装されていますが、C#に置き換えて実装したいと考えています。

単層パーセプトロン

絵が多いものはブログではなく、スライド形式でアップロードしていこうと思います。

Github

コーディングしたものは随時追加していきます。

github.com

【C#】WPFアプリケーション入門 #10 オブジェクト指向

はじめに

いままで扱ってきたクラスやメソッドなどはオブジェクト指向の考え方に沿って動いています。実はオブジェクト指向を調べると、人によって解釈が異なります。最近はオブジェクト指向という考え方は必須ではない傾向にあるので、ぼんやり「こんなもんかな」程度の認識でもいいです。実装中はわざわざオブジェクト指向を考えたりしないと思うので...。

お品書き

今回扱う内容です。

  1. オブジェクト指向
  2. オブジェクト指向の個人的解釈
  3. オブジェクト指向は必要か

1. オブジェクト指向

オブジェクト指向とは次の3要素で構成されるプログラミング手法です。

これを意識してプログラミングするのが重要だという話だったのですが、最近はオブジェクト指向という考え方を否定する人がいます。今となってはどちらが正しいのかは明確ではありませんが、必要だと思えば意識すると良いかもしれません。

1.1 カプセル化

これは #9 の記事に説明があります。ユーザが直接触れられないようにデータを隠す(カプセルに入れて保護する)ことです。アプリの中心はデータを扱うところにありますが、ユーザによって予期せぬデータが操作された場合、アプリが停止する可能性があります。よって、ユーザは間接的に操作できるようにするような仕組みにすれば、中身をいじられることはありません。
また、複雑な処理 (内部処理) を抽象化することで簡単な構造でデータを扱えるようになります。

1.2 継承

扱うデータやメソッドなどの操作系を含めた設計図をクラスといいました。クラスをいくつか作成したとき、そこに共通のデータがある場合は大元のクラスにまとめればいいわけです。これを受け継げば、どのクラスも大元のクラスのデータを利用することができます。
つまり、無駄にいくつも同じデータを用意せずに一か所にまとめて、それを参照できるようにすれば効率的という考え方です。
大元のクラスを基底クラス、基底クラスを参照するクラスを派生クラスといいます。 Java では親クラス子クラスといいます。

1.3 ポリモーフィズム(多様性)

これは一番厄介ですね。多様性といわれてもピンと来ないかもしれません。簡単に言うと、同じメソッド名でも条件によって動作が異なるように動かせることです。
車を例に考えてみます。車にはアクセルとブレーキが付いています。もちろん、アクセルを踏めば加速して、ブレーキを踏めば減速します。すべての車は同じ操作で加減速できるわけですが、車種によって性能が異なります。つまり、大元の操作は同じですが、車種という条件によってデータの扱いが異なります。このようにして共通のメソッドでも条件によってデータの扱いを変えることができます。これが多様性です。

2. オブジェクト指向の個人的解釈

一般に考えるオブジェクト指向が上記の通りですが、私の考えるオブジェクト指向は次の通りです。

2.1 クラスとメソッド

クラスは設計図ですが、メソッドは何かが問題です。メソッドは関数として考えれば、複数の処理をひとまとまりにすることができます。
メソッドは動作でクラスは動作に必要なデータの集合体です。メソッド自体もクラスに含まれるので、集合体の一つとして扱えます。メソッドがメソッドを呼ぶようなイメージです。
そもそも、オブジェクト指向はモノとして扱えるというのが大まかな意味です。なので、UI を配置した時点で UI に関するデータが用意されます。例えば Button を配置するとしましょう。すると、Buttonにはこのようなデータが用意されます。

  • Background (ボタンの背景色)
  • Content (ボタンに表示する文字)
  • Fontsize (ボタンに表示する文字の大きさ)

このほかにもたくさんのパラメータがあります。これらは Button クラスに含まれる、ボタンに関するデータの集合体です。さて、デザインにてボタンをダブルクリックすると、OnClick( ) メソッドが自動で生成されたと思います。これこそがボタンに関する処理です。

このように Button というモノ (UI) にはクラスが用意されており、クリックされたときにどうするかというメソッドを作ることができます。クラスとメソッドがセットになって Button というオブジェクトを作っていると考えると自然でしょう。これが私の考えるオブジェクト指向です。

2.2 継承

継承は 1.2 で説明した通りで、基底クラスでデータを一括でまとめておけば派生クラスから再利用 (何度も参照) できるので、設計図自体をモノ (情報のかたまり) として扱えるという点です。

2.3 インスタンス

クラスを扱うにはインスタンス化が必要です。クラスを用意するだけでは利用できないので、インスタンス化によって実体化させないといけません。実体化したデータ (フィールドやメソッド) はメンバと呼ばれ、外部から使用するためにはアクセシビリティの指定でアクセス許可することも必要です。

2.4 オブジェクト指向はどこからオブジェクトなのか

これも個人的見解です。オブジェクト = モノ ということを考えれば、今まで記述してきたことすべてが当てはまります。つまり、こうです。

f:id:takunology:20190710021608p:plain

ここで、かたまりを考えます。例えば派生クラスは基底クラスから継承されているので、情報のかたまりとしてのオブジェクトです。UI と派生クラス1は UI とそれに関するメソッド、およびクラスを含むのでこのかたまりもオブジェクトです。これらを合わせれば、UI の元をたどれば基底クラスまで含まれるので、アプリ全体は1つのオブジェクトとして考えられますね。
と考えると、継承しているところはすでに1つのモノになるのでこの時点でオブジェクトになるのではないかと...。

3. オブジェクト指向は必要か

大規模なアプリを作る場合はオブジェクト指向を考慮したほうが設計しやすく、共同作業者で情報や考え方を共有できるので必要になると思います。一人で開発するときや、小規模なら深く考えずに実装してもいいと思います。ただし、継承やメソッドなどの関係を考慮するなら必要であると思います。

おわりに

オブジェクト指向を完全に理解するのは難しいです。そもそも概念なので、人によっては解釈が異なることがあります。今回は私の考えるオブジェクト指向も記載しましたが、世間一般のエンジニアの方々から見れば「何言ってるんだ」といわれるでしょう。

オブジェクト指向は本当に難しいです。