VampireSurvivorsのホロライブMOD用JSONファイルを独自クラスを使って読み込もう
はじめに
この記事ではC#を使いJSONファイルから元クラスを推測し、デシリアライズをつかい読み込みます。
今回のターゲットはUnityで使われる「TexturePacker」が作ったJSONファイルを読み込みます。
具体的には「Vampire Survivors」用に提供されている、ホロライブのキャラクタに変更できる「Hololive mod」を使用し、その中に入っている「characters.json」を解析していこうと思います。
ファイルのフォルダ階層は以下になります。
\Vampire Survivors\resources\app.webpack\renderer\assets\img\characters.json
JSONファイル用のクラスを作る
JSONファイルを開き観察する
JSONファイルの基本の形は
“キー”:値
となっています。
それを考え、最初のほうを見ると、
{
"textures": [
{
"image": "characters.png",
"format": "RGBA8888",
"size": {
"w": 252,
"h": 398
},
"scale": 1,
"frames": [
{
"filename": "_0x00000000_i01.png",
"frame": {"x":2,"y":2,"w":41,"h":48},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":41,"h":48},
"sourceSize": {"w":41,"h":48}
},
“textures”:[….]
となっているのがわかります。[]はかっこでの使用ではなく、配列という意味です。これから”textures”が配列であることがわかります。
その配列の中に
“image”: “characters.png”,
“format”: “RGBA8888”,
“size”: { “w”: 252, “h”: 398 },
“scale”: 1,
“frames”: [ {…},{…},{…}…..]
というプロパティがあるのがわかります。
これをクラスにすると
public class Textures
{
[JsonPropertyName("image")]
public string Image { get; set; }
[JsonPropertyName("format")]
public string Format { get; set; }
[JsonPropertyName("size")]
public Size size { get; set; }
[JsonPropertyName("scale")]
public int scale { get; set; }
[JsonPropertyName("frames")]
public Frame[] frames { get; set; }
}
public class Size
{
public int w { get; set; }
public int h { get; set; }
}
と置き換えることができます。Sizeはw,hをもつクラスとして作りました。Frameはクラスを作って、あとから中身を作っていきます。
Frame配列のJSONの中身は次のようになっていることから、
{
"filename": "_0x00000000_i01.png",
"frame": {"x":2,"y":2,"w":41,"h":48},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":41,"h":48},
"sourceSize": {"w":41,"h":48}
},
これをクラスに置き換えると
public class Frame
{
[JsonPropertyName("filename")]
public string Filename { get; set; }
[JsonPropertyName("frame")]
public Rect frm { get; set; }
public bool rotated { get; set; }
public bool trimmed { get; set; }
[JsonPropertyName("spriteSourceSize")]
public Rect SpriteSourceSize { get; set; }
[JsonPropertyName("sourceSize")]
public Size Source { get; set; }
}
と表すことができます。
あとは最後のほうに
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:39fb0c7edd866d9f02d620f9a650dade:9bd7eef946b8fb91c63b2fbb2586bdc2:a5fe7db4b869eb0f3e0b2940b9577ea8$"
}
というメンバーがあるのでこれを置き換えると、
public class Meta
{
[JsonPropertyName("app")]
public string app { get; set; }
[JsonPropertyName("version")]
public string Version { get; set; }
public string smartupdate { get; set; }
}
このようになります。
Jsonファイルから推測したクラスの完成
これを全部置き換えたクラスを用意しました。
class FileAnalyze
{
public FileAnalyze(string filePath)
{
ReadAll(filePath);
}
public TexturepackerFile file;
void ReadAll(string filepath)
{
string ResumeJson = File.ReadAllText(filepath);
file = JsonSerializer.Deserialize < TexturepackerFile >(ResumeJson);
}
void WriteAll(string filePath)
{
}
}
/// <summary>
/// テクスチャーパックファイルのJSONファイル用クラス
/// </summary>
public class TexturepackerFile
{
public Textures[] textures { get; set; }
public Meta meta { get; set; }
}
public class Meta
{
public string app { get; set; }
public string version { get; set; }
public string smartupdate { get; set; }
}
public class Textures
{
[JsonPropertyName("image")]
public string Image { get; set; }
[JsonPropertyName("format")]
public string Format { get; set; }
[JsonPropertyName("size")]
public Size size { get; set; }
[JsonPropertyName("scale")]
public int scale { get; set; }
[JsonPropertyName("frames")]
public Frame[] frames { get; set; }
}
public class Size
{
public int w { get; set; }
public int h { get; set; }
}
public class Rect
{
public int x { get; set; }
public int y { get; set; }
public int w { get; set; }
public int h { get; set; }
}
public class Frame
{
[JsonPropertyName("filename")]
public string Filename { get; set; }
[JsonPropertyName("frame")]
public Rect frm { get; set; }
public bool rotated { get; set; }
public bool trimmed { get; set; }
[JsonPropertyName("spriteSourceSize")]
public Rect SpriteSourceSize { get; set; }
[JsonPropertyName("sourceSize")]
public Size Source { get; set; }
}
これを読み込むにはファイルを開いて読み込んだ後に、Deserializeでクラスのインスタンスにする必要があります。コードは次のようになります。
file = JsonSerializer.Deserialize < TexturepackerFile >(ResumeJson);
これでJSONファイルの中身をデシリアライズし、今回作ったクラスの中に入れています。
ファイルを読み込むためのアプリを作る
windowsの.netを使ってファイルを開くアプリを作りました。
ボタンを押すと今まで書いたコードを実行します。
ボタンをおして読み込むための大切な部分のソースだけ参考に書いておきます。
using System.Text;
using System.Text.Json;
を入れるのを忘れないでください。
private void btnOpen_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.FileName = "test.json";
ofd.InitialDirectory = @"C:\";
ofd.Filter = "JSONファイル(*.json)|*.json|すべてのファイル(*.*)|*.*";
//タイトルを設定する
ofd.Title = "ファイルを選択してください";
ofd.RestoreDirectory = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
this.jsonfile = new FileAnalyze(ofd.FileName);
if(jsonfile != null)
{
for(int i = 0; i < jsonfile.file.textures[0].frames.Length; i++)
{
listBox1.Items.Add(jsonfile.file.textures[0].frames[i].Filename);
}
}
}
}
実行するとこのようになります。
これでJSONの内容を保存するクラスができたことがわかりました。
まとめ
今回はJSONファイルを読んで、自分でクラスに書き換える方法を説明しました。クラスの中に情報が入っているので簡単に加工することができます。また、このクラスをシリアライズすることによりデータを保存することもできます。
最近はJSONでのデータ受け渡しも増えてきています。割と簡単にJSONファイルのクラスを作ることができるので、参考にされてみてはいかがでしょうか。