📗
APIから受け取ったJSONデータをUnityで辞書型に変換する方法
前書き
作っているもののオプション設定を作ろうと思い、たどり着いた解決方法です。
参照の記事をもとにChatGPTで解決することができました。
やりたいこと
- APIでロールプレイの設定の情報取得できるように
本題
APIの処理
api.py
from fastapi import FastAPI
import subprocess
import os
import character_roleplay
app = FastAPI()
@app.get("/roll_model")
def roll_model():
return character_roleplay.create_character_dialogue()
if __name__ == "__main__":
name, ex = os.path.splitext(os.path.basename(__file__))
subprocess.run(f"uvicorn {name}:app --reload")
ロールプレイ用の名前とファイルパスを返すコード
character_roleplay.py
import glob
import json
def create_character_dialogue():
data = []
file_paths = glob.glob('historys/roll/*.json')
for file_path in file_paths:
with open(file_path, encoding="UTF-8") as f:
character_data = json.load(f)
character_info = {
"name":character_data['character_name'],
"path":file_path.replace('\\', '/')
}
data.append(character_info)
return {'data': data}
ディレクトリ構造
ディレクトリ
├─.venv
├─historys
│ └─roll
│ └─ローラモデルファイル
├─app.py
├─character_roleplay.py
└─onnxruntime.dll
ロールモデルのJSON
JSONの中身
{
"character_name":"AI",
"system_message" : "日常的な会話が得意です。ユーザーとお話がしたいです。",
"initial_messages":[
{
"speaker": "ユーザー",
"text": "こんにちは。"
},
{
"speaker": "システム",
"text": "こんにちは、ユーザーさん。"
}
]
}
Unityの処理
受け取る想定のJSON
getjson
{
"data":[
{
"name":"AI",
"path":"historys/roll/assistant_history.json"
},
{
"name":"平成ギャル",
"path":"historys/roll/gal_history.json"
},
{
"name":"ずんだもん",
"path":"historys/roll/zundamon_history.json"
}
]
}
JSONデータの構造に合ったC#クラスを作成します。
JSONデータにはdata
キーがあり、その値はオブジェクトの配列です。
各オブジェクトにはname
とpath
というキーがあります。
以下のクラスを作成します。
[System.Serializable]
public class MyData
{
public string name;
public string path;
}
[System.Serializable]
public class DataContainer
{
public List<MyData> data;
}
次に、JSON文字列を辞書型に変換するコード。
public class JSONParser : MonoBehaviour
{
private string serverURL = "http://127.0.0.1:8000/"; // サーバーのURL
void Start()
{
StartCoroutine(FetchDataFromAPI());
}
// JSON文字列を辞書型に変換するメソッド
public Dictionary<string, string> ParseJSON(string jsonString)
{
// JSON文字列をDataContainerクラスにデシリアライズ
DataContainer container = JsonUtility.FromJson<DataContainer>(jsonString);
// 辞書型に変換
Dictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (var data in container.data)
{
dictionary[data.name] = data.path;
}
return dictionary;
}
// APIからデータを取得する関数
private IEnumerator FetchDataFromAPI()
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(serverURL + "roll_model"))
{
yield return webRequest.SendWebRequest();
if (webRequest.result == UnityWebRequest.Result.Success)
{
string jsonText = webRequest.downloadHandler.text;
Debug.Log(jsonText);
Dictionary<string, string> dataDictionary = ParseJSON(jsonText);
// 辞書型データを使用
foreach (var kvp in dataDictionary)
{
Debug.Log($"Name: {kvp.Key}, Path: {kvp.Value}");
}
}
else
{
Debug.LogError("APIリクエストが失敗しました: " + webRequest.error);
}
}
}
}
このコードでは、JSON文字列をDataContainerクラスにデシリアライズし、その後、Dictionary<string, string>に変換しています。最終的に、dataDictionaryとして辞書型データを取得し、使用することができます。
全体のコード
JSONParser.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
[System.Serializable]
public class MyData
{
public string name;
public string path;
}
[System.Serializable]
public class DataContainer
{
public List<MyData> data;
}
public class JSONParser : MonoBehaviour
{
private string serverURL = "http://127.0.0.1:8000/"; // サーバーのURL
void Start()
{
StartCoroutine(FetchDataFromAPI());
}
// JSON文字列を辞書型に変換するメソッド
public Dictionary<string, string> ParseJSON(string jsonString)
{
// JSON文字列をDataContainerクラスにデシリアライズ
DataContainer container = JsonUtility.FromJson<DataContainer>(jsonString);
// 辞書型に変換
Dictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (var data in container.data)
{
dictionary[data.name] = data.path;
}
return dictionary;
}
// APIからデータを取得する関数
private IEnumerator FetchDataFromAPI()
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(serverURL + "roll_model"))
{
yield return webRequest.SendWebRequest();
if (webRequest.result == UnityWebRequest.Result.Success)
{
string jsonText = webRequest.downloadHandler.text;
Debug.Log(jsonText);
Dictionary<string, string> dataDictionary = ParseJSON(jsonText);
// 辞書型データを使用
foreach (var kvp in dataDictionary)
{
Debug.Log($"Name: {kvp.Key}, Path: {kvp.Value}");
}
}
else
{
Debug.LogError("APIリクエストが失敗しました: " + webRequest.error);
}
}
}
}
余談
はじめは以下のようなJSONで受け取ろうとしていたのですがJsonUtility
ではパースできないことが分かったので、data
キーをつけることにしました。
{
{
"name":"AI",
"path":"historys/roll/assistant_history.json"
},
{
"name":"平成ギャル",
"path":"historys/roll/gal_history.json"
},
{
"name":"ずんだもん",
"path":"historys/roll/zundamon_history.json"
}
}
参照
Discussion