无法使用 JsonUtility 反序列化数据 [重复]
Posted
技术标签:
【中文标题】无法使用 JsonUtility 反序列化数据 [重复]【英文标题】:Cannot deserialize data with JsonUtility [duplicate] 【发布时间】:2019-12-30 10:45:11 【问题描述】:我是使用 Json 的新手,我无法弄清楚为什么数据没有反序列化。我尝试了很多东西,但我不知道问题是什么。 首先我需要从这个链接获取数据https://jsonplaceholder.typicode.com/users 然后我需要反序列化它。 (需要使用REST请求)
每当我想使用任何属性时,它都会告诉我它的 NULL“NullReferenceException:对象引用未设置为对象的实例”
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Net;
using System.IO;
public class Houses : MonoBehaviour
public GameObject Prefab;
void Update()
if (Input.GetKey(KeyCode.T))
onClick();
public void onClick()
UnityWebRequest request = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/users");
RootObject[] rootObjects = JsonUtility.FromJson<RootObject[]>(request.downloadHandler.text);
//Debug.Log(request.downloadHandler.text);
//foreach (var item in rootObjects)
//
// Debug.Log(item.id);
//
//----------------------------------------------------------------------------------------
//Latitude is the Y axis, longitude is the X axis
//for (int i = 0; i < rootObjects.Length; i++)
//
// float x = float.Parse(rootObjects[i].address.geo.lng);
// float y = float.Parse(rootObjects[i].address.geo.lat);
// Instantiate(Prefab, new Vector3(x, y, 0f), Quaternion.identity);
//
//public class ListItems
//
// //public RootObject[] rootObjects;
//public List<RootObject> rootObjects;
//
[System.Serializable]
public class Geo
public string lat get; set;
public string lng get; set;
[System.Serializable]
public class Address
public string street get; set;
public string suite get; set;
public string city get; set;
public string zipcode get; set;
public Geo geo get; set;
[System.Serializable]
public class Company
public string name get; set;
public string catchPhrase get; set;
public string bs get; set;
[System.Serializable]
public class RootObject
public int id; // get; set;
public string name get; set;
public string username get; set;
public string email get; set;
public Address address get; set;
public string phone get; set;
public string website get; set;
public Company company get; set;
如果有人可以帮助我,我将不胜感激。
编辑: 所以我做了一些改变。多亏了你们,我没有给 UnityWebRequest 时间来获取数据。 现在我得到一个不同的错误“ArgumentException:JSON 必须代表一个对象类型。”
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Net;
using System.IO;
public class Houses : MonoBehaviour
public GameObject Prefab;
public string jsonURL;
void Update()
if (Input.GetKeyUp(KeyCode.T))
onClick();
public void processJsonData(string _url)
RootObject[] rootObjects = JsonUtility.FromJson<RootObject[]>(_url);
Debug.Log(rootObjects[0].id);
IEnumerator getData()
Debug.Log("Procesing data, please wait.");
//WWW _www = new WWW(jsonURL);
UnityWebRequest request = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/users");
yield return request.SendWebRequest();
if (request.error == null)
processJsonData(request.downloadHandler.text);
else
Debug.Log("Oops something went wrong.");
public void onClick()
//----------------------------------------------------------------------------------------
//Latitude is the Y axis, longitude is the X axis
//for (int i = 0; i < rootObjects.Length; i++)
//
// float x = float.Parse(rootObjects[i].address.geo.lng);
// float y = float.Parse(rootObjects[i].address.geo.lat);
// Instantiate(Prefab, new Vector3(x, y, 0f), Quaternion.identity);
//
StartCoroutine(getData());
//public class ListItems
//
// //public RootObject[] rootObjects;
//public List<RootObject> rootObjects;
//
[System.Serializable]
public class Geo
public string lat;
public string lng;
[System.Serializable]
public class Address
public string street;
public string suite;
public string city;
public string zipcode;
public Geo geo;
[System.Serializable]
public class Company
public string name;
public string catchPhrase;
public string bs;
[System.Serializable]
public class RootObject
public int id;
public string name;
public string username;
public string email;
public Address address;
public string phone;
public string website;
public Company company;
```
【问题讨论】:
你能试试JsonConvert.DeserializeObject<RootObject[]>(request.downloadHandler.text)
吗?在你调试的时候,你在request.downloadHandler.text
看到了什么价值?
你在哪里发送请求?
对不起,我没有提到这一点,我需要使用 JsonUtility(这是我需要做的作业)。但它仍然不允许我使用 JsonConvert。
我需要向此链接jsonplaceholder.typicode.com/users 发送请求并从中获取信息以使用它。我什至不知道我是否正确使用了 UnityWebRequest,因为我对此很陌生。
@Selvin 在使用UnityWebRequest.Get
时会自动分配它,它会创建一个新的UnityWebRequest
,其中包含下载文本的标准获取请求所需的所有组件。
【参考方案1】:
Untiy 的JsonUtility 是一个相对高效但也极其有限的序列化程序。它只支持序列化fields,而你试图反序列化的对象完全由properties组成,它不支持。
(顺便说一句,Unity 的默认序列化程序不支持属性,这也是为什么它们不显示在编辑器中而字段支持的原因。)
由于它不知道如何设置属性,所以它不知道,并且该属性保持其默认值。对于引用类型(string
、Address
等),默认值为 NULL,这使得尝试访问它们会引发异常。
在你的情况下,你所要做的就是改变你想要反序列化的类,这样:
public class Geo
public string lat get; set;
public string lng get; set;
变成这样:
public class Geo
public string lat;
public string lng;
为你的所有课程都这样做,你应该是金子。
编辑:正如 Philip B. 在他的回答中提到的,您也没有正确使用 UnityWebRequest.Get
。
UnityWebRequest
不会立即解析,您必须从 Unity Coroutine 内部对它进行 yield return...
处理,或者等待它通过阻塞循环解析,如下所示:
UnityWebRequest request = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/users");
request.SendWebRequest();
while (!request.isDone)
当然,这被认为是非常糟糕的形式,因为它会冻结游戏直到下载数据。但是,under the hood Unity handles the downloads on background threads,因此您在等待时不会阻止下载本身。
您还应该查询请求以查看是否出现任何错误,以便您可以根据需要处理它们,因为您可能还会遇到下载本身的问题。
if (request.isHttpError || request.isNetworkError)
//... handle errors here
else
RootObject[] rootObjects = JsonUtility.FromJson<RootObject[]>(request.downloadHandler.text);
但是,我真的建议您在此处使用 Unity 的 UnityWebRequest.Get
documentation 中描述的协程。如果您是 Unity Coroutines 的新手,请read up,它是 Unity 开发的宝贵工具。
编辑 2: Per this answer JsonUtility 不支持将数组序列化为***对象,因此您必须首先将数组包装在一个对象中,然后对其进行反序列化。您还必须使 json 文件中的***对象成为包含该数组的对象。
[Serializable]
public class Routes
public RootObject[] roots;
如果您不控制文件的内容,(这个想法再次来自我链接到的那个出色的答案),您可以使用一些字符串魔术来做到这一点。
string jsonString = $@"""roots"":request.downloadHandler.text";
【讨论】:
所以你说我需要摆脱所有的 get;放; ?我试过了,但我仍然得到同样的错误。 查看我的编辑,Phillip B. 没有正确使用网络请求是正确的。 谢谢:)。我编辑了我的帖子,现在出现了另一个错误 @Klemen 这实际上是一个新问题,因为现在看来您现在成功下载的文本格式为 Unity JsonUtility 无法理解的格式。请结帐Serialize and Deserialize Json and Json Array in Unity 在那里添加了另一个编辑,祝你好运。【参考方案2】:您正在尝试访问为 NULL 的 request.downloader.text
(因此“NullReferenceException:对象引用未设置为对象的实例”),因为您没有发送 GET 请求。
如果您点击此链接 on how to use UnityWebRequest.Get,您会发现您需要的不仅仅是 UnityWebRequest.Get("Your_Url");
从 URL 中获取您的 JSON 字符串。
尝试以下方法:
public void onClick()
using (UnityWebRequest request = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/users"))
request.SendWebRequest();
RootObject[] rootObjects = JsonUtility.FromJson<RootObject[]>(request.downloadHandler.text);
希望这会对你有所帮助。
【讨论】:
这甚至不会编译 我试过了,我只是删除了yield return
,因为我有 void 并添加了Debug.Log(rootObjects[0].id);
以查看它是否有效,它仍然给了我同样的错误。
@Selvin 谢谢,我的错误在这里。
@Klemen,你能尝试调试一下,看看你的 request
里面有什么吗?检查您的request.downloadHandler
是否为空。
是的,它为空。因为我没有给它时间来获取数据。我制作了一个 IEnumerator 来获取数据。以上是关于无法使用 JsonUtility 反序列化数据 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Unity 5.4 中使用 JsonUtility 反序列化 JSON。子集合始终为空
Unity中使用JsonUtility.FromJson反序列化JSON