在Unity中序列化和反序列化Json和Json数组

在Unity中序列化和反序列化Json和Json数组

问题描述:

我有一个使用WWW从PHP文件发送到统一文件的项目列表.

I have a list of items send from a PHP file to unity using WWW.

WWW.text看起来像:

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

我在哪里修剪string中多余的[].当我尝试使用Boomlagoon.JSON解析它时,仅检索第一个对象.我发现我必须deserialize()该列表并导入了MiniJSON.

Where I trim the extra [] from the string. When I try to parse it using Boomlagoon.JSON, only the first object is retrieved. I found out that I have to deserialize() the list and have imported MiniJSON.

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

But I am confused how to deserialize() this list. I want to loop through every JSON object and retrieve data. How can I do this in Unity using C#?

我正在使用的班级是

public class player
{
    public string playerId { get; set; }
    public string playerLoc { get; set; }
    public string playerNick { get; set; }
}

修剪[]之后,我可以使用MiniJSON解析json.但是它仅返回第一个KeyValuePair.

After trimming the [] I am able to parse the json using MiniJSON. But it is returning only the first 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));
}

谢谢!

Unity添加了 JsonUtility 5.3.3 更新后对其API进行修改.除非您正在做更复杂的事情,否则请不要理会所有第三方库. JsonUtility比其他Json库更快.更新到Unity 5.3.3 版本或更高版本,然后尝试以下解决方案.

Unity added JsonUtility to their API after 5.3.3 Update. Forget about all the 3rd party libraries unless you are doing something more complicated. JsonUtility is faster than other Json libraries. Update to Unity 5.3.3 version or above then try the solution below.

JsonUtility是轻量级的API.仅支持简单类型.它不支持字典等集合. List是一个例外.它支持ListList数组!

JsonUtility is a lightweight API. Only simple types are supported. It does not support collections such as Dictionary. One exception is List. It supports List and List array!

如果您需要序列化Dictionary或执行其他操作而不是简单地序列化和反序列化简单数据类型,请使用第三方API.否则,请继续阅读.

If you need to serialize a Dictionary or do something other than simply serializing and deserializing simple datatypes, use a third-party API. Otherwise, continue reading.

要序列化的示例类:

[Serializable]
public class Player
{
    public string playerId;
    public string playerLoc;
    public string playerNick;
}

1.一个数据对象(非数组JSON)

对A部分进行序列化:

序列化到Json >方法.

Serialize to Json with the public static string ToJson(object obj); method.

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部分:

序列化到Json >方法重载.只需将true传递给JsonUtility.ToJson函数即可格式化数据.将下面的输出与上面的输出进行比较.

Serialize to Json with the public static string ToJson(object obj, bool prettyPrint); method overload. Simply passing true to the JsonUtility.ToJson function will format the data. Compare the output below to the output above.

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部分:

反序列化 json与 public static T FromJson(string json); 方法重载.

Deserialize json with the public static T FromJson(string json); method overload.

string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
Player player = JsonUtility.FromJson<Player>(jsonString);
Debug.Log(player.playerLoc);

反序列化B部分:

反序列化 json与 public static object FromJson(string json, Type type); 方法重载.

Deserialize json with the public static object FromJson(string json, Type type); method overload.

string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
Player player = (Player)JsonUtility.FromJson(jsonString, typeof(Player));
Debug.Log(player.playerLoc);


对C部分进行反序列化:

反序列化 json与 public static void FromJsonOverwrite(string json, object objectToOverwrite); 方法.使用JsonUtility.FromJsonOverwrite时,将不会创建要反序列化的该对象的新实例.它将仅重用您传入的实例并覆盖其值.

Deserialize json with the public static void FromJsonOverwrite(string json, object objectToOverwrite); method. When JsonUtility.FromJsonOverwrite is used, no new instance of that Object you are deserializing to will be created. It will simply re-use the instance you pass in and overwrite its values.

这是有效的,应尽可能使用.

This is efficient and should be used if possible.

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.多个数据(ARRAY JSON)

您的Json包含多个数据对象.例如,playerId出现的次数大于一次. Unity的JsonUtility不支持数组,因为它仍然是新数组,但是您可以使用

Your Json contains multiple data objects. For example playerId appeared more than once. Unity's JsonUtility does not support array as it is still new but you can use a helper class from this person to get array working with JsonUtility.

创建一个名为JsonHelper的类.从下面直接复制JsonHelper.

Create a class called JsonHelper. Copy the JsonHelper directly from below.

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

Powai

User2


如果这是服务器上的Json数组,而您不是手动创建的:

您可能必须在收到的字符串前添加{"Items":,然后在其末尾添加}.

You may have to Add {"Items": in front of the received string then add } at the end of it.

我为此做了一个简单的功能:

I made a simple function for this:

string fixJson(string value)
{
    value = "{\"Items\":" + value + "}";
    return value;
}

然后您可以使用它:

string jsonString = fixJson(yourJsonFromServer);
Player[] player = JsonHelper.FromJson<Player>(jsonString);


3.不带&&类反序列化json字符串使用数字属性反序列化Json

这是一个以数字或数字属性开头的Json.

This is a Json that starts with a number or numeric properties.

例如:

{ 
"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's JsonUtility does not support this because the "15m" property starts with a number. A class variable cannot start with an integer.

从Unity的 Wiki 下载 SimpleJSON.cs .

Download SimpleJSON.cs from Unity's wiki.

要获取USD的"15m"属性:

To get the "15m" property of USD:

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

要获取ISK的"15m"属性,请执行以下操作:

To get the "15m" property of ISK:

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

要获取NZD的"15m"属性,请执行以下操作:

To get the "15m" property of NZD:

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

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

The rest of the Json properties that doesn't start with a numeric digit can be handled by Unity's JsonUtility.

4.麻烦的JsonUtility:

使用JsonUtility.ToJson进行序列化时出现问题吗?

Problems when serializing with JsonUtility.ToJson?

使用JsonUtility.ToJson获取空字符串或"{}"吗?

Getting empty string or "{}" with JsonUtility.ToJson?

A .确保该类不是数组.如果是这样,请将上面的帮助程序类与JsonHelper.ToJson而不是JsonUtility.ToJson一起使用.

A. Make sure that the class is not an array. If it is, use the helper class above with JsonHelper.ToJson instead of JsonUtility.ToJson.

B .将[Serializable]添加到要序列化的类的顶部.

B. Add [Serializable] to the top of the class you are serializing.

C .从类中删除属性.例如,在变量public string playerId { get; set; } 删除 { get; set; }中. Unity无法序列化它.

C. Remove property from the class. For example, in the variable, public string playerId { get; set; } remove { get; set; }. Unity cannot serialize this.

使用JsonUtility.FromJson反序列化时出现问题吗?

Problems when deserializing with JsonUtility.FromJson?

A .如果得到Null,请确保Json不是Json数组.如果是这样,请将上面的帮助程序类与JsonHelper.FromJson而不是JsonUtility.FromJson一起使用.

A. If you get Null, make sure that the Json is not a Json array. If it is, use the helper class above with JsonHelper.FromJson instead of JsonUtility.FromJson.

B .如果反序列化时出现NullReferenceException,请在类的顶部添加[Serializable].

B. If you get NullReferenceException while deserializing, add [Serializable] to the top of the class.

C .其他任何问题,请确认您的json有效.在此处转到此站点并粘贴json.它应该显示json是否有效.它还应该使用Json生成适当的类.只需确保从每个变量中删除删除 { get; set; },并将[Serializable]添加到所生成的每个类的顶部即可.

C.Any other problems, verify that your json is valid. Go to this site here and paste the json. It should show you if the json is valid. It should also generate the proper class with the Json. Just make sure to remove remove { get; set; } from each variable and also add [Serializable] to the top of each class generated.

Newtonsoft.Json:

如果出于某些原因必须使用 Newtonsoft.Json ,请查看Unity的分叉版本此处.请注意,如果使用某些功能,则可能会崩溃.小心点.

If for some reason Newtonsoft.Json must be used then check out the forked version for Unity here. Note that you may experience crash if certain feature is used. Be careful.

回答您的问题:

您的原始数据是

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

添加 {"Items":在其前面中,然后添加 }在其中.

Add {"Items": in front of it then add } at the end of it.

执行此操作的代码:

serviceData = "{\"Items\":" + serviceData + "}";

现在您拥有:

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

要将php中的多个数据串行化为数组,您现在可以

To serialize the multiple data from php as arrays, you can now do

public player[] playerInstance;
playerInstance = JsonHelper.FromJson<player>(serviceData);

playerInstance[0]是您的第一个数据

playerInstance[1]是您的第二个数据

playerInstance[2]是您的第三个数据

或具有playerInstance[0].playerLocplayerInstance[1].playerLocplayerInstance[2].playerLoc ......的类中的数据...

or data inside the class with playerInstance[0].playerLoc, playerInstance[1].playerLoc, playerInstance[2].playerLoc ......

您可以使用playerInstance.Length来检查长度,然后再访问它.

You can use playerInstance.Length to check the length before accessing it.

注意:player类中删除 { get; set; }.如果您有{ get; set; },它将不起作用. Unity的JsonUtility不能与定义为属性的类成员一起使用.

NOTE: Remove { get; set; } from the player class. If you have { get; set; }, it won't work. Unity's JsonUtility does NOT work with class members that are defined as properties.