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

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

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

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

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

4回答

679閲覧

UnityでのJsonシリアライズについて

kado_index

総合スコア8

C#

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

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2018/05/11 09:32

編集2018/05/11 10:42

前提・実現したいこと

UnityでJsonUtility.fromJson()を用いて以下のようなjsonをシリアライズしたく思っています。
が、データ構造はあっているつもりなのになかなかエラーが消えません。

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

NullReferenceException: A null value was found where an object instance was required.

変換したいjson

{ "status": "ok", "data": { "model": [ { "id": 1, "name": "名前", "path": "http://aaa.com", "created_at": "2018-01-01 00:00:00", "updated_at": "2018-01-01 00:00:00" }, { "id": 2, "name": "名前", "path": "http://bbb.com", "created_at": "2018-01-01 00:00:00", "updated_at": "2018-01-01 00:00:00" } ] } }

該当のソースコード

CSharp

1 [Serializable] 2 public class ServerResponseWith<T> 3 { 4 public string status; 5 public T data; 6 } 7 8 //複数の要素を持つ 9 [Serializable] 10 public class ListData<T> 11 { 12 public List<T> model; 13 } 14 15 16 //modelに含まれるデータ 17 [Serializable] 18 public class ModelsData 19 { 20 public string id; 21 public string name; 22 public string path; 23 public string created_at; 24 public string updated_at; 25 }

CSharp

1Action<UnityWebRequest> serverConnectSuccess = (UnityWebRequest www) => 2 { 3 string downloadedText = www.downloadHandler.text; 4 5 ServerResponseWith<ListData<ModelsData>> serverResponse = JsonUtility.FromJson<ServerResponseWith<ListData<ModelsData>>>(downloadedText); 6 7 if (serverResponse.status == "ok"){ 8 List<ModelsData> models = serverResponse.data.model; 9 } 10 }

試したこと

List<ModelsData>じゃなく、ModelData[]にしたりなど様々なことを試してもnullしか帰って来ず困っています。
JsonUtilityはList<>のネストに対応していないみたいなのも見かけたのですが、この形のjsonはシリアライズできないのでしょうか、ご教授願います。
よろしくお願いします。

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

Unity 2017.4.1f1 personal
C#
macOS high Sieera

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

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

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

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

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

Rocky

2018/05/11 10:11

エラーメッセージが発生するC#のコード箇所も提示いただくと、回答率があがりますよ。
kado_index

2018/05/11 10:41

ごめんなさい。jsonの初期仕様の方から引張って来たミスで、実際にサーバーから帰ってくるのは"model"です
kado_index

2018/05/16 17:11

エラーメッセージの出る箇所も載せたほうがいいとのアドバイスありがとうございました!今回は事故いけつしたので追加で載せたりはしませんでしたが、今後質問する際は気をつけます!ありがとうございました!
guest

回答4

0

自己解決

みなさま様々な解決方法の提案をいただきありがとうございました。
C#のコード規約に引っかかっていたようです。
CA1006: Do not nest generic types in member signatures
再利用性を高めるために、ServerResponceWith -> ListData -> ModelsDataと三段階でジェネリックのネストをかけていたのですが、これがデザインとしてよくなかったようです。
再利用性は諦めて、ListDataとModelDataのをジェネリックで繋がず、それぞれ明示的に定義することで機能的には解決しました。(ListDataはModelsに名前を変更しました)

//元々List<T>だったやつ [Serializable] public class Models { public List<ModelsData> model; } //modelに含まれるデータ [Serializable] public class ModelsData { public string id; public string name; public string path; public string created_at; public string updated_at; }
//JsonUtilityを使ってた行 ServerResponseWith<Models> serverResponse = JsonUtility.FromJson<ServerResponseWith<Models>>(downloadedText);

UnityのJsonUtilityで自分の例よりも複雑なJsonをパースする際には、このように分けて書きたくなる気もするのですが、C#の規約違反じゃあどうにもならないので諦めようと思います。
また、サーバーからのレスポンスが複数体のモデルが帰ってくるにも関わらずmodelsではなく名前がmodelなのはおかしいとのご指摘ですが、自分ももやもやを抱えてるので、サーバーエンジニアの方と相談します。

投稿2018/05/16 17:09

編集2018/05/16 17:18
kado_index

総合スコア8

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

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

0

リファレンスには「内部的には、このメソッドは Unity のシリアライザーを使用します」とか「Serializable 属性でマークされているプレーンなクラスか構造体でなければなりません」といった記述があるのが気になりますね...
JSONをジェネリック型に展開しようとしているのがまずいのかもしれません。ジェネリック型の利点が損なわれるのがちょっと不満ですが、下記のような型を追加して、

C#

1[Serializable] 2public class ServerResponseWithModelsData : ServerResponseWith<ListDataModelsData> 3{ 4} 5 6[Serializable] 7public class ListDataModelsData : ListData<ModelsData> 8{ 9}

JSONからの読み込みもこの型を使ってみてはどうでしょうか?

C#

1ServerResponseWithModelsData serverResponse = JsonUtility.FromJson<ServerResponseWithModelsData>(downloadedText);

参考:UnityのJsonUtilityの細かい10の疑問をいまさら検証した - Qiita

投稿2018/05/15 20:40

Bongo

総合スコア10807

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

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

kado_index

2018/05/16 17:15

ジェネリックを複数回回していたのが諸悪の根源でした。。。 1回だけのネストの場合はジェネリックでも動くのですが、それを超えるとC#的にダメみたいです。。。 解決方法としては最も近い回答でした。お答えいただき本当にありがとうございました。
guest

0

実際動かしていないのだけど、

public class ModelsData {   public string id {get;set;}   public string name {get;set;} public string path {get;set;} public string created_at {get;set;} public string updated_at {get;set;} }

という感じで、プロパティにしないとだめじゃないの?
メタプログラミングするとわかるけど、プロパティとフィールドは、全く別物だよ。

あと、複数のものは適切に複数形にしていないのは、糞コードなので何とかした方がいいともいます。

投稿2018/05/14 15:47

kiichi54321

総合スコア1984

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

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

0

ざっくりとしか読みつつですが
List<ModelsData> models = serverResponse.data.model;

List<ModelsData> models = serverResponse.data.models;
にしないとうまく動かないのでは?

投稿2018/05/11 10:10

Rocky

総合スコア261

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問