提问人:dil33pm 提问时间:3/27/2016 最后编辑:Snakdil33pm 更新时间:7/16/2023 访问量:276231
在 Unity 中序列化和反序列化 Json 和 Json 数组
Serialize and Deserialize Json and Json Array in Unity
问:
我有一个使用 PHP 文件发送到 unity 的项目列表。WWW
如下所示:WWW.text
[
{
"playerId": "1",
"playerLoc": "Powai"
},
{
"playerId": "2",
"playerLoc": "Andheri"
},
{
"playerId": "3",
"playerLoc": "Churchgate"
}
]
我从 .当我尝试使用 解析它时,只检索第一个对象。我发现我必须进入列表并导入了 MiniJSON。[]
string
Boomlagoon.JSON
deserialize()
但是我很困惑如何列出这个列表。我想遍历每个JSON对象并检索数据。如何使用 C# 在 Unity 中执行此操作?deserialize()
我使用的类是
public class player
{
public string playerId { get; set; }
public string playerLoc { get; set; }
public string playerNick { get; set; }
}
修剪后,我可以使用 MiniJSON 解析 json。但它只返回第一个.[]
KeyValuePair
IDictionary<string, object> players = Json.Deserialize(serviceData) as IDictionary<string, object>;
foreach (KeyValuePair<string, object> kvp in players)
{
Debug.Log(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
}
谢谢!
答:
不要修剪,你应该没事。 标识一个 JSON 数组,该数组正是您能够迭代其元素所需的。[]
[]
就像@Maximiliangerhardt说的,MiniJson没有正确反序列化的能力。我使用了 JsonFx 并且像魅力一样工作。与[]
player[] p = JsonReader.Deserialize<player[]>(serviceData);
Debug.Log(p[0].playerId +" "+ p[0].playerLoc+"--"+ p[1].playerId + " " + p[1].playerLoc+"--"+ p[2].playerId + " " + p[2].playerLoc);
Unity 在 5.3.3 更新后将 JsonUtility 添加到其 API 中。忘记所有第三方库,除非您正在做一些更复杂的事情。JsonUtility 比其他 Json 库更快。更新到 Unity 5.3.3 或更高版本,然后尝试以下解决方案。
JsonUtility
是一个轻量级的 API。仅支持简单类型。它不支持 Dictionary 等集合。一个例外是 。它支持和阵列!List
List
List
如果需要序列化或执行除简单地序列化和反序列化简单数据类型以外的其他操作,请使用第三方 API。否则,请继续阅读。Dictionary
要序列化的示例类:
[Serializable]
public class Player
{
public string playerId;
public string playerLoc;
public string playerNick;
}
1. 一个数据对象(非数组 JSON)
序列化 A 部分:
使用公共静态字符串 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 部分:
使用公共静态字符串 ToJson(object obj, bool prettyPrint);
方法重载序列化为 Json。只需传递给函数即可格式化数据。将下面的输出与上面的输出进行比较。true
JsonUtility.ToJson
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"
}
反序列化 A 部分:
使用公共静态 T FromJson(string json);
方法重载反序列化 json。
string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
Player player = JsonUtility.FromJson<Player>(jsonString);
Debug.Log(player.playerLoc);
反序列化 B 部分:
使用公共静态对象 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 部分:
使用公共静态 void FromJsonOverwrite(string json, object objectToOverwrite);
方法反序列化 json。使用时,不会创建要反序列化到的该 Object 的新实例。它只会重用您传入的实例并覆盖其值。JsonUtility.FromJsonOverwrite
这是有效的,如果可能,应该使用。
Player playerInstance;
void Start()
{
//Must create instance once
playerInstance = new Player();
deserialize();
}
void deserialize()
{
string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
//Overwrite the values in the existing class instance "playerInstance". Less memory Allocation
JsonUtility.FromJsonOverwrite(jsonString, playerInstance);
Debug.Log(playerInstance.playerLoc);
}
2. 多个数据(数组JSON)
您的 Json 包含多个数据对象。例如,出现不止一次。Unity 不支持数组,因为它仍然是新的,但您可以使用此人的帮助程序类来获取数组。playerId
JsonUtility
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);
输出:
波瓦伊
用户 2
如果这是来自服务器的 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 不支持此功能,因为“15m”属性以数字开头。类变量不能以整数开头。JsonUtility
从 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);
要获得新西兰元的“15m”属性:
var N = JSON.Parse(yourJsonString);
string price = N["NZD"]["15m"].Value;
Debug.Log(price);
其余不以数字开头的 Json 属性可以由 Unity 的 JsonUtility 处理。
4.JsonUtility故障排除:
使用 JsonUtility.ToJson
序列化时出现问题?
获取空字符串或带有 “” 的 ?{}
JsonUtility.ToJson
答:确保该类不是数组。如果是,请使用上面的帮助程序类,而不是 .JsonHelper.ToJson
JsonUtility.ToJson
B.B. 添加到要序列化的类的顶部。[Serializable]
C.C. 从类中删除属性。例如,在变量中,删除 .Unity 无法对此进行序列化。public string playerId { get; set; }
{ get; set; }
使用 JsonUtility.FromJson
反序列化时出现问题?
答:如果得到 ,请确保 Json 不是 Json 数组。如果是,请使用上面的帮助程序类,而不是 .Null
JsonHelper.FromJson
JsonUtility.FromJson
B. 如果在反序列化时得到,请添加到类的顶部。NullReferenceException
[Serializable]
三.任何其他问题,请验证您的 json 是否有效。在此处转到此站点并粘贴 json。它应该显示 json 是否有效。它还应该使用 Json 生成正确的类。只需确保从每个变量中删除 remove,并添加到生成的每个类的顶部即可。{ get; set; }
[Serializable]
Newtonsoft.Json:
如果出于某种原因必须使用 Newtonsoft.Json,那么从 2022 年 2 月起,现在可以直接从 Unity 获取它:[email protected]。只需通过包管理器添加即可。有关详细信息,请参阅通过 kalle (jag) 通过 UPM 安装官方版。com.unity.nuget.newtonsoft-json
您还可以查看 SaladLab / 的 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
注意:从类中删除。如果有,它将不起作用。Unity 不适用于定义为属性的类成员。{ get; set; }
player
{ get; set; }
JsonUtility
评论
JsonUtility.FromJson
{ get; set; }
player
{ get; set; }
player
JsonHelper
JsonHelper
List
你必须添加到类中,像这样:[System.Serializable]
PlayerItem
using System;
[System.Serializable]
public class PlayerItem {
public string playerId;
public string playerLoc;
public string playerNick;
}
假设你得到了一个这样的 JSON
[
{
"type": "qrcode",
"symbol": [
{
"seq": 0,
"data": "HelloWorld9887725216",
"error": null
}
]
}
]
要在 Unity 中解析上述 JSON,您可以像这样创建 JSON 模型。
[System.Serializable]
public class QrCodeResult
{
public QRCodeData[] result;
}
[System.Serializable]
public class Symbol
{
public int seq;
public string data;
public string error;
}
[System.Serializable]
public class QRCodeData
{
public string type;
public Symbol[] symbol;
}
然后简单地按以下方式解析...
var myObject = JsonUtility.FromJson<QrCodeResult>("{\"result\":" + jsonString.ToString() + "}");
现在您可以根据需要修改 JSON/CODE。https://docs.unity3d.com/Manual/JSONSerialization.html
评论
Debug.Log(myObject.result[0].symbol[0].data);
for(var i = 0; i <= myObject.result.Length - 1; i ++) { Debug.Log(myObject.result[i].type); }
foreach (var item in myObject.result) { Debug.Log(item.type); }
要读取 JSON 文件,请参阅以下简单示例
您的 JSON 文件 (StreamingAssets/Player.json)
{
"Name": "MyName",
"Level": 4
}
C# 脚本
public class Demo
{
public void ReadJSON()
{
string path = Application.streamingAssetsPath + "/Player.json";
string JSONString = File.ReadAllText(path);
Player player = JsonUtility.FromJson<Player>(JSONString);
Debug.Log(player.Name);
}
}
[System.Serializable]
public class Player
{
public string Name;
public int Level;
}
评论
File.ReadAllText
你可以只使用添加到你的项目并使用下面的脚本Newtonsoft.Json
Newtonsoft.dll
using System;
using Newtonsoft.Json;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
[Serializable]
public class Person
{
public string id;
public string name;
}
public Person[] person;
private void Start()
{
var myjson = JsonConvert.SerializeObject(person);
print(myjson);
}
}
另一种解决方案是使用 JsonHelper
using System;
using Newtonsoft.Json;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
[Serializable]
public class Person
{
public string id;
public string name;
}
public Person[] person;
private void Start()
{
var myjson = JsonHelper.ToJson(person);
print(myjson);
}
}
评论
如果您使用的是 Vector3,这就是我所做的
1-我创建了一个类,将其命名为Player
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class Player
{
public Vector3[] Position;
}
2-那我这样称呼它
if ( _ispressed == true)
{
Player playerInstance = new Player();
playerInstance.Position = newPos;
string jsonData = JsonUtility.ToJson(playerInstance);
reference.Child("Position" + Random.Range(0, 1000000)).SetRawJsonValueAsync(jsonData);
Debug.Log(jsonData);
_ispressed = false;
}
3-这就是结果
“位置”:[ {“x”:-2.8567452430725099,“y”:-2.4323320388793947,“z”:0.0}]}
Unity <= 2019 年
Narottam Goyal 有一个好主意,将数组包装在一个 json 对象中,然后反序列化为一个结构体。 下面使用泛型来解决所有类型的数组的问题,而不是每次都创建一个新类。
[System.Serializable]
private struct JsonArrayWrapper<T> {
public T wrap_result;
}
public static T ParseJsonArray<T>(string json) {
var temp = JsonUtility.FromJson<JsonArrayWrapper<T>>("{\"wrap_result\":" + json + "}");
return temp.wrap_result;
}
它可以通过以下方式使用:
string[] options = ParseJsonArray<string[]>(someArrayOfStringsJson);
Unity 2020 大会
在 Unity 2020 中,有一个官方的 newtonsoft 包,它是一个更好的 json 库。
评论
com.unity.nuget.newtonsoft-json
如果你来这里寻找如何使用 JsonUtility 序列化列表,而不需要任何额外的包,请继续阅读。
[System.Serializable]
public class JsonableListWrapper<T>
{
public List<T> list;
public JsonableListWrapper(List<T> list) => this.list = list;
}
用法示例:
List<string> stringList = new List<string>(){"one","two","three"};
// To Json
string stringListAsJson = JsonUtility.ToJson(new JsonListWrapper<string>(stringList));
// From Json
List<string> stringListFromJson = JsonUtility.FromJson<JsonListWrapper<string>>(stringListAsJson).list;
归功于这个线程的唯一缘故:https://forum.unity.com/threads/jsonutilities-tojson-with-list-string-not-working-as-expected.722783/
似乎你不能直接序列化/反序列化一个列表,但如果它是类的属性,你可以。在我个人的情况下,我将字符串类型替换为自定义类的类型,效果很好。
评论
[
]
List<PlayerLocation>
Newtonsoft.Json
Json.Deserialize()
IDictionary<string,object>
List<object>
IDictionary<string,object>
KeyValuePair<>