質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Q&A

解決済

2回答

617閲覧

C# のオブジェクトの JSON 文字列へのシリアライズ、JSON 文字列から C# のオブジェクトへのデシリアライズについて

syosn938

総合スコア4

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

0グッド

0クリップ

投稿2022/12/22 06:00

編集2023/01/05 04:23

前提

Unityでハンドトラッキングを利用したシステムを作っています。
指先の3次元座標をListに格納しラッパーを用いてjson形式で書き込み・読み出しをしようとしています。書き込むシーンと読み出すシーンが異なるためjsonファイルを経由したいです。
PositionList.csで書き込み、TargetRoad.csで読み出しを行う想定です。

実現したいこと

  • json形式で保存したファイルから3次元座標情報を順次取り出したい。そのためにC# のオブジェクトの JSON 文字列へのシリアライズ、JSON 文字列から C# のオブジェクトへのデシリアライズを行う

発生している問題・エラーメッセージ

・エラーは出ていないが TargetRoad.cs 内の position に座標データが入っていない。
→TargetRoad.cs の position = JsonUtility.FromJson<Vector3>(datastr);の箇所でposition にうまく値が入れられていないと思うのですが自分の知識では手詰まりでした。
position に入れたいデータの例は{"data":[{"test":[{"x":-0.07575902342796326,"y":1.2197943925857545,"z":0.018420785665512086}]},{"test":[{"x":-0.1992444545030594,"y":1.255491852760315,"z":0.0342610627412796}]},{"test":[{"x":-0.2881636917591095,"y":1.182250738143921,"z":0.03852791339159012}]}]}です。
画像のヒエラルキーはPositionList.csを使っているものでTargetRoad.csは別のシーンで使っています。

イメージ説明

該当のソースコード

C#

1//PositionList.cs 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using System.IO; 6using System; 7using System.Runtime.Serialization; 8using System.Runtime.Serialization.Json; 9using System.Runtime.Serialization.Formatters.Binary; 10using System.Linq; 11 12[Serializable] 13public class Position 14{ 15 public float x; 16 public float y; 17 public float z; 18 19 public Position(float X, float Y, float Z) 20 { 21 x = X; 22 y = Y; 23 z = Z; 24 } 25 26} 27 28[Serializable] 29public class SaveDataWrapper 30{ 31 public List<Data> data; 32 33 public SaveDataWrapper() 34 { 35 data = new List<Data>(); 36 } 37} 38 39[Serializable] 40public class Data 41{ 42 43 public Data(List<Position> Ex) 44 { 45 test = Ex; 46 } 47 48 public List<Position> test; 49} 50 51public class PositionList : MonoBehaviour 52{ 53 public GameObject obj; 54 List<Vector3> posList = new List<Vector3>(); 55 public SaveDataWrapper sdw = new SaveDataWrapper(); 56 57 [SerializeField] 58 public string json; 59 60 // Update is called once per frame 61 public void ButtonClickSet() 62 { 63 Transform myTransform = this.transform; 64 Vector3 worldPos = myTransform.position; 65 float x = worldPos.x; 66 float y = worldPos.y; 67 float z = worldPos.z; 68 69 Instantiate(obj, new Vector3(x, y, z), Quaternion.identity); 70 Position pos = new Position(x,y,z); 71 List<Position> positions = new List<Position>(); 72 /*Addする*/ 73 positions.Add((Position)pos.DeepCopy()); 74 Data data = new Data(positions); 75 76 sdw.data.Add((Data)data.DeepCopy()); 77 78 79 } 80 /* public List<Vector3> GetPosList() 81 { 82 return posList; 83 }*/ 84 85 public void Check() 86 { 87 StreamWriter writer; 88 json = JsonUtility.ToJson(sdw); 89 writer = new StreamWriter(Application.dataPath + "/savedata.json"); 90 writer.Write(json); 91 writer.Flush(); 92 writer.Close(); 93 Debug.Log("check"); 94 95 96 } 97 98} 99 100public static class Extention 101{ 102 //参照渡し回避用(オブジェクトのコピー) 103 public static object DeepCopy(this object target) 104 { 105 object result; 106 BinaryFormatter b = new BinaryFormatter(); 107 MemoryStream mem = new MemoryStream(); 108 109 try 110 { 111 b.Serialize(mem, target); 112 mem.Position = 0; 113 result = b.Deserialize(mem); 114 } 115 finally 116 { 117 mem.Close(); 118 } 119 120 return result; 121 } 122}

C#

1//TargetRoad.cs 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using System.IO; 6using System; 7using System.Runtime.Serialization; 8using System.Runtime.Serialization.Json; 9using System.Runtime.Serialization.Formatters.Binary; 10using System.Linq; 11 12public class TargetRoad : MonoBehaviour 13{ 14 // Start is called before the first frame update 15 public void OnDestroy() 16 { 17 string datastr = ""; 18 StreamReader reader; 19 reader = new StreamReader(Application.dataPath + "/savedata.json"); 20 datastr = reader.ReadToEnd(); 21 reader.Close(); 22 23 position = JsonUtility.FromJson<Vector3>(datastr);//ここの記述に問題がありそうだと推測しています。 24 Debug.Log(position);//出力は(0.00,0.00,0.00)となった。 25 float x = position.x; 26 float y = position.y; 27 float z = position.z; 28 29 Instantiate(obj, new Vector3(x, y, z), Quaternion.identity); 30 } 31 32 public GameObject obj; 33 public Vector3 position; 34} 35 36

試したこと

Debug.Logでposition内に座標データが反映されていないことが確認できました。
position = JsonUtility.FromJson<Vector3>(datastr);のVector3をPositionに変えるとerror CS0029:Cannot implicitly convert type Position to UnityEngine.Vector3.と出ました。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/12/22 07:20

Vector3 の定義と JSON 文字列のサンプルを質問欄を編集して追記してもらえませんか? C# の問題として、C# のオブジェクトの JSON 文字列へのシリアライズ、JSON 文字列から C# のオブジェクトへのデシリアライズの話の範囲に限ってもらえると、回答が集まりやすいかも。
YAmaGNZ

2022/12/22 07:36

なんでデシリアライズするときはVector3なんですか?
YAmaGNZ

2023/01/05 04:59

自分が何の型をJSONとして記録しているか把握されていないのでしょうか? json = JsonUtility.ToJson(sdw); とsdwをJSON化してます。sdwってPosition型じゃないでしょう。 デシリアライズ側も position = JsonUtility.FromJson<Position>(datastr); としてもpositionはVector3として定義しているのだし、型が違います。 同じ型にデシリアライズして取り出しましょう。
syosn938

2023/01/05 06:15

皆様ご助言ありがとうございました。 シリアライズ・デシリアライズについてよくわかっておらず拙い質問をしてしまいました。 型の把握によって理解が深まり、解決することが出来ました。
guest

回答2

0

回答作成中に自己解決してしまったようですが、せっかく書いたので以下に載せておきます。

position に入れたいデータの例は{"data":[{"test":[{"x":-0.07575902342796326,"y":1.2197943925857545,"z":0.018420785665512086}]},{"test":[{"x":-0.1992444545030594,"y":1.255491852760315,"z":0.0342610627412796}]},{"test":[{"x":-0.2881636917591095,"y":1.182250738143921,"z":0.03852791339159012}]}]}です。

最初にそういう形式の JSON 文字列ありきでそこから話が始まるのであれば、それから C# のクラス定義を作って、JSON 文字列をそのクラスのオブジェクトにデシリアライズしてはいかがですか?

Visual Studio を使っているのであれば、以下の記事のようにして C# のクラス定義を作成できます。

JSON 文字列から C# のクラス定義生成
http://surferonwww.info/BlogEngine/post/2020/05/10/generate-class-definition-from-json-string.aspx

上の JSON 文字列からは以下のように C# のクラス定義が作成できます。

public class Rootobject { public Datum[] data { get; set; } } public class Datum { public Test[] test { get; set; } } public class Test { public float x { get; set; } public float y { get; set; } public float z { get; set; } }

これを使って以下のようにデシリアライズ/シリアライズができます。(注:以下のコードでは Newtonsoft.Json を使っています)

using System; using Newtonsoft.Json; namespace ConsoleAppJsonUtility { internal class Program { static void Main(string[] args) { string jsonString = "{\"data\":[" + "{\"test\":[{\"x\":-0.07575902342796326,\"y\":1.2197943925857545,\"z\":0.018420785665512086}]}," + "{\"test\":[{\"x\":-0.1992444545030594,\"y\":1.255491852760315,\"z\":0.0342610627412796}]}," + "{\"test\":[{\"x\":-0.2881636917591095,\"y\":1.182250738143921,\"z\":0.03852791339159012}]}]}"; var rootObject = JsonConvert.DeserializeObject<Rootobject>(jsonString); foreach(Datum datum in rootObject.data) { foreach(Test test in datum.test) { Console.WriteLine($"x: {test.x}, y: {test.y}, z: {test.z}"); } } Console.WriteLine("-----------------------------------------------"); string jsonString2 = JsonConvert.SerializeObject(rootObject, Formatting.Indented); Console.WriteLine(jsonString2); } } }

実行結果は:

イメージ説明

投稿2023/01/05 06:44

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自己解決

public SaveDataWrapper sdw_;をTargetRoadクラスに作り、同じ型にデシリアライズ。
var x = sdw_.data[0].test[0].xの様に読み出した。

投稿2023/01/05 06:13

syosn938

総合スコア4

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問