一体化 Json 和 Json 数组的序列化和反序列化

我有一个项目清单从 PHP 文件发送到统一使用 WWW

WWW.text看起来像:

[
{
"playerId": "1",
"playerLoc": "Powai"
},
{
"playerId": "2",
"playerLoc": "Andheri"
},
{
"playerId": "3",
"playerLoc": "Churchgate"
}
]

在那里我修剪额外的 []string。当我尝试使用 Boomlagoon.JSON解析它时,只检索第一个对象。我发现我必须 deserialize()的列表,并已导入 MiniJSON。

但我很困惑如何 deserialize()这个名单。我想循环遍历每个 JSON 对象并检索数据。我如何在 Unity 中使用 C # 做到这一点?

我使用的类是

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));
}

谢谢!

248115 次浏览

不要修剪 [],你应该没问题。[]标识一个 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更新后将 杰森公用事业公司添加到他们的 API 中。忘记所有的第三方库,除非你正在做一些更复杂的事情。JsonUtility 比其他 Json 库更快。更新到 Unity 5.3.3或以上版本,然后尝试下面的解决方案。

JsonUtility是一个轻量级 API。只支持简单类型。它支持诸如 Dictionary 之类的集合。一个例外是 List。它支持 ListList数组!

如果需要序列化 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。只需将 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 :

使用 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);

反序列化 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时,将不会创建要反序列化的 Object 的任何新实例。它将简单地重用您传入的实例并覆盖其值。

这是有效的,如果可能的话应该使用。

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 包含多个数据对象。例如,playerId一次出现得更多。Unity 的 JsonUtility不支持数组,因为它仍然是新的,但是你可以使用这个人的 帮手类让 数组JsonUtility一起工作。

创建一个名为 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. 不使用 class 反序列化 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 的 维基百科下载 SimpleJSON.cs

获得美元的“1500万”资产:

var N = JSON.Parse(yourJsonString);
string price = N["USD"]["15m"].Value;
Debug.Log(price);

为了获得 ISK 的“1500万”资产:

var N = JSON.Parse(yourJsonString);
string price = N["ISK"]["15m"].Value;
Debug.Log(price);

获得新西兰“1500万”资产:

var N = JSON.Parse(yourJsonString);
string price = N["NZD"]["15m"].Value;
Debug.Log(price);

其余不以数字开头的 Json 属性可以由 Unity 的 JsonUtility 处理。


4. 解决 JsonUtility 的问题:

JsonUtility.ToJson序列化时的问题?

得到空字符串或“ {}”与 JsonUtility.ToJson

A .确保该类不是数组。如果是的话,使用上面的 helper 类和 JsonHelper.ToJson而不是 JsonUtility.ToJson

[Serializable]添加到要序列化的类的顶部。

C 。从类中删除属性。例如,在变量中,public string playerId { get; set; } 拿开 { get; set; }。 Unity 不能序列化这个属性。

JsonUtility.FromJson反序列化时的问题?

A .如果得到 Null,请确保 Json 不是 Json 数组。如果是的话,使用上面的 helper 类和 JsonHelper.FromJson而不是 JsonUtility.FromJson

如果在反序列化时得到 NullReferenceException,将 [Serializable]添加到类的顶部。

C .任何其他问题,请验证您的 json 是否有效。转到这个站点 给你并粘贴 json。它会显示 json 是否有效。它还应该使用 Json 生成适当的类。只要确保从每个变量中删除 拿开{ get; set; },并将 [Serializable]添加到生成的每个类的顶部。


牛顿软件:

如果出于某种原因 牛顿软件,杰森必须使用,那么到2022年2月,它现在可以直接从 Unity 从这里获得: Nuget.newtonsoft-json@3.0。只需通过包管理器添加 com.unity.nuget.newtonsoft-json。详情见 通过 UPM 正式安装 by 卡莱(捷豹)

你也可以从 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].playerLocplayerInstance[1].playerLocplayerInstance[2].playerLoc... ..。

在访问它之前,可以使用 playerInstance.Length检查长度。

注意: 拿开 { get; set; }来自 player类。如果你有 { get; set; },它不会工作。Unity 的 JsonUtility与定义为 物业的类成员一起工作。

你必须把 [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
}
]
}
]

为了统一地解析上面的 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

要读取 JSON 文件,请参考这个简单的示例

您的 JSON 文件(StreamingAsset/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;
}

您可以使用 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);


}
}

enter image description here

另一种解决方案是使用 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);


}
}

enter image description here

如果你正在使用 Vector3,这就是我所做的

1-我创建了一个类 Name it 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.432320388793947,“ z”: 0.0}}}

统一 < = 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);

统一2020

在 Unity 2020中有一个官方的 Newtonsoft包,它是一个更好的 json 库。