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

Number of views 48

我项目的服务端使用PHP,并在数据库中存储了如下数据信息。

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

Unity的前端项目使用www获取请求。

请求到的内容如下:

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

我删除了字符串中多余的 []。当我尝试使用 Boomlagoon.JSON 库解析时,只获取到了第一个对象。我发现需要对列表进行反序列化(deserialize()),而且我也已经导入了 MiniJSON。

但我该如何反序列化这个列表?我想遍历每个 JSON 对象并获取数据。如何在 Unity 中使用 C# 实现这一点?

这是我定义的Player类:

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

要正确地在 Unity 中处理从服务器获取的 JSON 数据,你需要确保完整地解析整个 JSON 数组,并且将每个 JSON 对象映射到你的 Player 类。以下是一个完整的示例,展示如何使用 MiniJSON 库来完成这个任务。

首先,确保你已经导入了 MiniJSON 库。你可以通过 NuGet 或者直接将 MiniJSON 的源代码添加到你的项目中。

接下来,你需要修改你的 Player 类,以匹配 JSON 数据中的字段名:

public class Player
{
    public string playerId { get; set; }
    public string playerLoc { get; set; }
    // 注意:JSON 数据中没有 "playerNick" 字段,所以这里不需要
}

然后,你可以编写一个方法来处理从服务器获取的数据并将其转换为 Player 对象的列表:

using UnityEngine;
using System.Collections.Generic;
using MiniJSON;

public class PlayerManager : MonoBehaviour
{
    void Start()
    {
        string serviceData = "[{\"playerId\": \"1\",\"playerLoc\": \"Powai\"},{\"playerId\": \"2\",\"playerLoc\": \"Andheri\"},{\"playerId\": \"3\",\"playerLoc\": \"Churchgate\"}]";

        List<Player> players = ParsePlayers(serviceData);

        foreach (var player in players)
        {
            Debug.Log($"Player ID: {player.playerId}, Location: {player.playerLoc}");
        }
    }

    List<Player> ParsePlayers(string json)
    {
        List<Player> players = new List<Player>();

        // 将 JSON 字符串解析为数组
        object[] jsonArray = Json.Deserialize(json) as object[];

        if (jsonArray != null)
        {
            foreach (object jsonObject in jsonArray)
            {
                if (jsonObject is IDictionary<string, object> jsonDict)
                {
                    Player player = new Player
                    {
                        playerId = jsonDict["playerId"] as string,
                        playerLoc = jsonDict["playerLoc"] as string
                    };

                    players.Add(player);
                }
            }
        }

        return players;
    }
}

在这个示例中,我们定义了一个 ParsePlayers 方法,该方法接受一个 JSON 字符串作为输入,并将其解析为 Player 对象的列表。我们首先将 JSON 字符串解析为一个对象数组,然后遍历这个数组,将每个对象解析为 Player 对象并添加到列表中。

最后,在 Start 方法中,我们调用 ParsePlayers 方法并打印出每个玩家的信息。

请注意,如果 JSON 数据格式有误或者不一致,可能会导致解析失败。因此,在实际应用中,建议添加适当的错误处理逻辑。

我发现unity有JsonUtility这个类,这个类能完成我所需的功能么?这样就不要使用外部库了

是的,Unity 提供了一个内置的 JsonUtility 类,可以用来序列化和反序列化 JSON 数据。使用 JsonUtility 可以避免引入外部库,使代码更简洁。

首先,我们需要定义一个包含 Player 对象的列表的类。我们可以使用 List<Player> 来表示这个列表。为了使用 JsonUtility,我们需要确保类是公共的(public)并且带有 [System.Serializable] 属性。

以下是完整的示例代码:

  1. 定义 Player 类:
[System.Serializable]
public class Player
{
    public string playerId;
    public string playerLoc;
}
  1. 定义包含 Player 列表的类:
[System.Serializable]
public class PlayerList
{
    public List<Player> players;
}
  1. 使用 JsonUtility 进行序列化和反序列化:
using UnityEngine;
using System.Collections.Generic;

public class PlayerManager : MonoBehaviour
{
    void Start()
    {
        string serviceData = "[{\"playerId\": \"1\",\"playerLoc\": \"Powai\"},{\"playerId\": \"2\",\"playerLoc\": \"Andheri\"},{\"playerId\": \"3\",\"playerLoc\": \"Churchgate\"}]";

        PlayerList playerList = JsonUtility.FromJson<PlayerList>(serviceData);

        foreach (var player in playerList.players)
        {
            Debug.Log($"Player ID: {player.playerId}, Location: {player.playerLoc}");
        }
    }
}

在这个示例中,我们定义了两个类:PlayerPlayerListPlayer 类表示单个玩家的信息,而 PlayerList 类包含一个 Player 对象的列表。

Start 方法中,我们使用 JsonUtility.FromJson<PlayerList> 方法将 JSON 字符串反序列化为 PlayerList 对象。然后,我们遍历 players 列表并打印每个玩家的信息。

这种方法利用了 Unity 内置的 JsonUtility 类,无需引入任何外部库,使代码更加简洁和易于维护。