我好生气?,Python,JS里面一两行代码能够搞定的Json读取,在Unity中使用C#读取Json文件超多坑,爬出来一个又来一个。
主要是JsonUtility.FromJson太不给力了。
最好的方式是,使用 https://github.com/jilleJr/Newtonsoft.Json-for-Unity 这个第三方库。详情见下。
在UnityEditor中运行程序时,如何读取Json
- Step 1: 先把对应的Json File放到 Assets/Resources 里面,假设该Json File的名字为:“my_file.json”
- Step 2: 对应着Json Object的格式,声明一个对应的类,例如:
[System.Serializable]
public class CustomerInfo
{
public string application_id;
public string assigned_staff;
public float arrive_time;
public float starting_process_time;
public float finish_time;
}
[System.Serializable]
public class CustomerInfoList
{
public List<CustomerInfo> customerApplications = new List<CustomerInfo>();
}
这里是第一个坑,[System.Serializable] 必不可少,否则无法JsonUtility无法解析。见文档说明:
Internally, this method uses the Unity serializer; therefore the type you are creating must be supported by the serializer. It must be a plain class/struct marked with the Serializable attribute. Fields of the object must have types supported by the serializer. Fields that have unsupported types, as well as private fields or fields marked with the NonSerialized attribute, will be ignored.
- Step 3: 使用Resources.Load读取Json File,详见文档
TextAsset jsonFile = Resources.Load<TextAsset>("my_file"); // 不需要.json 后缀
string jsonString = jsonFile.text
jsonString 案例:
“[ { “application_id”: “app_1”, “assigned_staff”: “staff_1”, “arrive_time”: 1, “starting_process_time”: 3, “finish_time”: 5 }, { “application_id”: “app_2”, “assigned_staff”: “staff_2”, “arrive_time”: 2, “starting_process_time”: 4, “finish_time”: 6 } ]”
- Step 4: 然后就是解析这个jsonString了。我试了有三种方法,
-
一个是使用Unity 提供的 JsonUtility.FromJson。 这里超多坑,不知道照着教程写的代码为什么会有类似于not serialzable的报错
- (几天后的更新): 我知道为什么了?!! JsonUtility.FromJson只能读取Json Object,当Json文件中包含的实际上是Json Array时,就会出错。正确的方式是
-
在Step 2中,定义一个Container,
[System.Serializable]
public class CustomerInfoList
{
public List customerApplications = new List();
} -
读取时,需要在上面的jsonString外面套一层“皮”,把Array变成Object
CustomerInfoList customerList = JsonUtility.FromJson(“{“customerApplications” :” +jsonString + “}”);
List customerApplication = customerList.customerApplications;在上面代码中,“{“customerApplications” :” 就是为了在jsonString套一层皮。其实 CustomerInfoList 这个类,也是在List()套了一层皮,所以CustomerInfoList里面是customerApplications,JsonUtility.FromJson 里面写的也是customerApplications.
-
- (几天后的更新): 我知道为什么了?!! JsonUtility.FromJson只能读取Json Object,当Json文件中包含的实际上是Json Array时,就会出错。正确的方式是
-
一个是使用第三方的库,例如Json.Net, 但是安装包好麻烦呀。
- (几天后的更新) JsonUtility.FromUtility真的太鸡肋了。如果Json文件里面含有复杂的数据结构,例如List, 或者List<List> 这种,就无法解析,因此还是逃不过使用第三方库。
- 仔细看了一下文档,安装其实也很简单(主要是文档写得密密麻麻的?
- 使用Json.Net(又名Newtonsoft.Json)解析各种Json的步骤:
- 安装:见文档
- 代码:
-
[System.Serializable]
public class StaffWithAssignedApplications
{
public string staff_id;
public List<List<string>> assigned_application_list_at_each_interval;
public Vector3 position;
}
[System.Serializable]
public class StaffContainer
{
public List<StaffWithAssignedApplications> staffs;
}
// 使用Networking.Json进行解析
using Newtonsoft.Json;
TextAsset jsonFile = Resources.Load<TextAsset>(fileName);
StaffContainer staffContainer = JsonConvert.DeserializeObject<StaffContainer>("{\"staffs\":" + jsonFile.text + "}");
- 第三种方法是自己手写了简单的解析器,但是不够可拓展。
using System.Collections.Generic;
using System.Text.RegularExpressions;
public static List<T> ParseJsonArray<T>(string json)
{
var regex = new Regex(@"\{(.+?)\}");
var matches = regex.Matches(json);
var list = new List<T>();
foreach (Match match in matches)
{
var itemJson = "{" + match.Groups[1].Value + "}";
var item = JsonUtility.FromJson<T>(itemJson);
list.Add(item);
}
return list;
}
// 调用:
List<CustomerInfo> finalResults = ParseJsonArray<CustomerInfo>(jsonString);
运行在Oculus或者手机上的程序,如何读取?
未完待续
总结Unity中读取Json文件的坑
- JsonUtility.FromJson 太鸡肋了,解析不了复杂的Json,直接放弃吧。使用Newtonsoft.Json
- 无论是JsonUtility.FromJson,还是Newtonsoft.Json(?这个待查证),都只能直接读取Json Object
{"key":value}
如果是文章来源:https://uudwc.com/A/YnWvM
[{"key":value},{"key":value},...]
这种形式,则读取的时候需要在外面套层皮:文章来源地址https://uudwc.com/A/YnWvM
{
"outkey": [{"key":value},{"key":value},...]
}
- 定义与Json Object相关的类的时候,需要加上System.Serializable