在Unity5.3.3更新后,Unity API新增了JsonUtility。除非你在进行更加复杂的操作,否则请不要考虑使用第三方库。相较于其他 Json 库,JsonUtility 更快。请升级到 Unity 版本5.3.3或以上版本,然后尝试以下解决方案。
JsonUtility
是一个轻量级的API,仅支持简单类型,不支持类似字典这样的集合。唯一的例外是List
,它支持对List
和List
数组进行序列化!
如果您需要序列化一个Dictionary
,或者需要进行除简单数据类型序列化和反序列化之外的其他操作,请使用第三方API。否则,请继续阅读。
以下是一个示例类:
[Serializable]
public class Player
{
public string playerId;
public string playerLoc;
public string playerNick;
}
1. 单个数据对象(非数组JSON)
部分A的序列化:
使用public static string ToJson(object obj);
方法将其序列化为Json格式。
Player playerInstance = new Player()
playerInstance.playerId = "8484239823"
playerInstance.playerLoc = "Powai"
playerInstance.playerNick = "Random Nick"
//Convert to JSON
string playerToJson = JsonUtility.ToJson(playerInstance)
Debug.Log(playerToJson)
输出:
{"playerId":"8484239823","playerLoc":"Powai","playerNick":"Random Nick"}
序列化部分 B:
使用public static string ToJson(object obj, bool prettyPrint);
方法重载将对象序列化为Json格式。简单地向JsonUtility.ToJson
函数传递true
将格式化数据。将下面的输出与上面的输出进行比较。
Player playerInstance = new Player()
playerInstance.playerId = "8484239823"
playerInstance.playerLoc = "Powai"
playerInstance.playerNick = "Random Nick"
//Convert to JSON
string playerToJson = JsonUtility.ToJson(playerInstance, true)
Debug.Log(playerToJson)
输出:
{
"playerId": "8484239823",
"playerLoc": "Powai",
"playerNick": "Random Nick"
}
反序列化 Part A:
使用public static T FromJson(string json);
方法重载来反序列化JSON。
string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}"
Player player = JsonUtility.FromJson<Player>(jsonString)
Debug.Log(player.playerLoc)
反序列化 Part B:
使用 public static object FromJson(string json, Type type);
方法重载进行json反序列化。
string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}"
Player player = (Player)JsonUtility.FromJson(jsonString, typeof(Player))
Debug.Log(player.playerLoc)
反序列化部分 C:
使用public static void FromJsonOverwrite(string json, object objectToOverwrite);
方法将 json 反序列化。当使用 JsonUtility.FromJsonOverwrite
时,不会创建需要反序列化的对象的新实例。它将简单地重复使用您传入的实例并覆盖其值。
这很高效,应该尽可能使用。
Player playerInstance;
void Start()
{
playerInstance = new Player();
deserialize();
}
void deserialize()
{
string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
JsonUtility.FromJsonOverwrite(jsonString, playerInstance);
Debug.Log(playerInstance.playerLoc);
}
2. 多个数据(数组JSON)
您的Json包含多个数据对象。例如,playerId
出现了多次。由于Unity的JsonUtility
仍然是新技术,因此不支持数组,但您可以使用helper这个人提供的类来使JsonUtility
与数组一起工作。
创建一个名为JsonHelper
的类。直接从下面复制JsonHelper。
public static class JsonHelper
{
public static T[] FromJson<T>(string json)
{
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
return wrapper.Items;
}
public static string ToJson<T>(T[] array)
{
Wrapper<T> wrapper = new Wrapper<T>();
wrapper.Items = array;
return JsonUtility.ToJson(wrapper);
}
public static string ToJson<T>(T[] array, bool prettyPrint)
{
Wrapper<T> wrapper = new Wrapper<T>();
wrapper.Items = array;
return JsonUtility.ToJson(wrapper, prettyPrint);
}
[Serializable]
private class Wrapper<T>
{
public T[] Items;
}
}
序列化Json数组:
Player[] playerInstance = new Player[2]
playerInstance[0] = new Player()
playerInstance[0].playerId = "8484239823"
playerInstance[0].playerLoc = "Powai"
playerInstance[0].playerNick = "Random Nick"
playerInstance[1] = new Player()
playerInstance[1].playerId = "512343283"
playerInstance[1].playerLoc = "User2"
playerInstance[1].playerNick = "Rand Nick 2"
//Convert to JSON
string playerToJson = JsonHelper.ToJson(playerInstance, true)
Debug.Log(playerToJson)
输出:
{
"Items": [
{
"playerId": "8484239823",
"playerLoc": "Powai",
"playerNick": "Random Nick"
},
{
"playerId": "512343283",
"playerLoc": "User2",
"playerNick": "Rand Nick 2"
}
]
}
反序列化 Json 数组:
string jsonString = "{\r\n \"Items\": [\r\n {\r\n \"playerId\": \"8484239823\",\r\n \"playerLoc\": \"Powai\",\r\n \"playerNick\": \"Random Nick\"\r\n },\r\n {\r\n \"playerId\": \"512343283\",\r\n \"playerLoc\": \"User2\",\r\n \"playerNick\": \"Rand Nick 2\"\r\n }\r\n ]\r\n}";
Player[] player = JsonHelper.FromJson<Player>(jsonString);
Debug.Log(player[0].playerLoc);
Debug.Log(player[1].playerLoc);
输出:
Powai
User2
如果这是来自服务器的Json数组且你不是手动创建的:
您可能需要在接收到的字符串前面添加
{"Items":
,然后在末尾添加
}
。
我为此编写了一个简单的函数:
string fixJson(string value)
{
value = "{\"Items\":" + value + "}";
return value;
}
然后你可以使用它:
string jsonString = fixJson(yourJsonFromServer)
Player[] player = JsonHelper.FromJson<Player>(jsonString)
3.没有类的反序列化json字符串和带数字属性的Json反序列化
这是以数字或数字属性开头的Json。
例如:
{
"USD" : {"15m" : 1740.01, "last" : 1740.01, "buy" : 1740.01, "sell" : 1744.74, "symbol" : "$"},
"ISK" : {"15m" : 179479.11, "last" : 179479.11, "buy" : 179479.11, "sell" : 179967, "symbol" : "kr"},
"NZD" : {"15m" : 2522.84, "last" : 2522.84, "buy" : 2522.84, "sell" : 2529.69, "symbol" : "$"}
}
Unity的JsonUtility不支持此操作,因为“15m”属性以数字开头。类变量不能以整数开头。
从Unity的
wiki下载SimpleJSON.cs。
获取USD的“15m”属性:
var N = JSON.Parse(yourJsonString)
string price = N["USD"]["15m"].Value
Debug.Log(price)
获取 ISK 的 "15m" 属性:
var N = JSON.Parse(yourJsonString)
string price = N["ISK"]["15m"].Value
Debug.Log(price)
获取NZD的“15m”属性:
var N = JSON.Parse(yourJsonString)
string price = N["NZD"]["15m"].Value
Debug.Log(price)
Json属性中不以数字开头的部分可以由Unity的JsonUtility处理。
4.故障排除JsonUtility:
使用JsonUtility.ToJson
序列化时出现问题?
使用JsonUtility.ToJson
得到空字符串或"{}
"?
A. 确保类不是数组。如果是,请改用上面的辅助类JsonHelper.ToJson
代替JsonUtility.ToJson
。
B. 在要序列化的类顶部添加[Serializable]
。
C. 从类中删除属性。例如,在变量public string playerId { get; set; }
中,删除{ get; set; }
。Unity无法序列化此内容。
使用JsonUtility.FromJson
反序列化时出现问题?
A. 如果得到Null
,请确保Json不是Json数组。如果是,请改用上面的辅助类JsonHelper.FromJson
代替JsonUtility.FromJson
。
B。如果在反序列化时出现NullReferenceException
,请在类顶部添加[Serializable]
。
C。如果出现其他问题,请验证您的json是否有效。转到此网站here并粘贴json。它应该向您显示json是否有效。它还应该使用Json生成适当的类。只需确保从每个变量中删除remove{ get; set; }
,并在生成的每个类的顶部添加[Serializable]
。
Newtonsoft.Json:
如果出于某些原因必须使用
Newtonsoft.Json,则从2022年2月起可以直接从Unity获取,链接在此处:
com.unity.nuget.newtonsoft-json@3.0。只需通过包管理器添加
com.unity.nuget.newtonsoft-json
即可。详见
通过UPM安装官方版本 by
kalle (jag)。
您还可以查看来自
SaladLab /
Json.Net.Unity3D 的Unity分支版本。请注意,如果使用某些功能可能会导致崩溃,请小心。
回答您的问题:
您的原始数据为
[{"playerId":"1","playerLoc":"Powai"},{"playerId":"2","playerLoc":"Andheri"},{"playerId":"3","playerLoc":"Churchgate"}]
在它前面添加{"Items":
,然后在末尾添加}
。
执行此操作的代码:
serviceData = "{\"Items\":" + serviceData + "}";
现在你有:
{"Items":[{"playerId":"1","playerLoc":"Powai"},{"playerId":"2","playerLoc":"Andheri"},{"playerId":"3","playerLoc":"Churchgate"}]}
要将来自PHP的多个数据序列化为数组,现在可以执行以下操作:
public player[] playerInstance
playerInstance = JsonHelper.FromJson<player>(serviceData)
playerInstance[0]
是你的第一份数据
playerInstance[1]
是你的第二份数据
playerInstance[2]
是你的第三份数据
或者是在类中使用 playerInstance[0].playerLoc
, playerInstance[1].playerLoc
, playerInstance[2].playerLoc
...... 来获取数据。
在访问前,你可以使用 playerInstance.Length
检查长度。
注意:从 player
类中移除 { get; set; }
。如果有 { get; set; }
,它将无法工作。Unity 的 JsonUtility
不适用于被定义为属性的类成员。
[
和]
呢?那才是它成为列表的关键。请不要再去掉它,将其反序列化为数组或列表,我相信它会正常工作的。请贴出你尝试过的代码。 - Jon SkeetList<PlayerLocation>
,因为这确实是一个数组。 - Maximilian GerhardtNewtonsoft.Json
中看到的那样),而是Json.Deserialize()
总是返回一个IDictionary<string,object>
给你,然后你操作List<object>
。请参考http://stackoverflow.com/a/22745634/5296568。最好使用一个更好的JSON反序列化器来进行你熟悉的反序列化。 - Maximilian GerhardtIDictionary<string,object>
。我能够取出值,但只有第一个KeyValuePair<>
。 - dil33pm