在Unity

时间:2016-03-26 19:13:21

标签: c# json unity3d

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

WWW.text看起来像:

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

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

但我很困惑如何deserialize()此列表。我想遍历每个JSON对象并检索数据。如何使用C#在Unity中执行此操作?

我正在使用的课程是

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

谢谢!

8 个答案:

答案 0 :(得分:175)

Unity在 5.3.3 更新后将JsonUtility添加到其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);方法将序列化为。

Player playerInstance = new Player();
playerInstance.playerId = "8484239823";
playerInstance.playerLoc = "Powai";
playerInstance.playerNick = "Random Nick";

//Convert to Jason
string playerToJason = JsonUtility.ToJson(playerInstance);
Debug.Log(playerToJason);

输出

{"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 Jason
string playerToJason = JsonUtility.ToJson(playerInstance, true);
Debug.Log(playerToJason);

输出

{
    "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时,不会创建要反序列化的对象的新实例。它只会重复使用您传入的实例并覆盖其值。

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

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不支持数组,因为它仍然是新的,但您可以使用此人的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 Jason
string playerToJason = JsonHelper.ToJson(playerInstance, true);
Debug.Log(playerToJason);

输出

{
    "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&amp;&amp;的情况下反序列化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不支持这一点,因为&#34; 15m&#34;物业以数字开头。类变量不能以整数开头。

从Unity wiki下载 SimpleJSON.cs

获得&#34; 15m&#34;美元的财产:

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

获得&#34; 15m&#34; ISK的财产:

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

获得&#34; 15m&#34;新西兰财产:

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

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

4.TROUBLESHOOTING JsonUtility:

使用JsonUtility.ToJson序列化时遇到的问题?

获取空字符串或&#34; {}&#34;与JsonUtility.ToJson

<强> A 即可。确保该类不是数组。如果是,请使用上面的帮助程序类JsonHelper.ToJson而不是JsonUtility.ToJson

<强>乙即可。将[Serializable]添加到要序列化的类的顶部。

<强> C 即可。从类中删除属性。例如,在变量public string playerId { get; set; } 删除 { get; set; }中。 Unity无法将其序列化。

使用JsonUtility.FromJson进行反序列化时遇到的问题?

<强> A 即可。如果得到Null,请确保Json不是Json数组。如果是,请使用上面的帮助程序类JsonHelper.FromJson而不是JsonUtility.FromJson

<强>乙即可。如果您在反序列化时获得NullReferenceException,请将[Serializable]添加到班级的顶部。

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

<强> Newtonsoft.Json:

如果出于某种原因必须使用 Newtonsoft.Json ,请查看Unity here的分叉版本。请注意,如果使用某些功能,您可能会遇到崩溃。小心。

回答您的问题

您的原始数据是

 [{"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 NOT 与定义为属性的类成员一起工作。

答案 1 :(得分:9)

假设你有一个像这样的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

答案 2 :(得分:0)

不要修剪[],你应该没事。 []标识一个JSON数组,它正是您能够迭代其元素所需的数据。

答案 3 :(得分:0)

像@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);

答案 4 :(得分:0)

要读取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;
}

答案 5 :(得分:0)

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

答案 6 :(得分:0)

如果您正在使用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}]}

答案 7 :(得分: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);

Unity 2020

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