RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 658811
Accepted
Алексей Шиманский
Алексей Шиманский
Asked:2020-04-26 19:45:50 +0000 UTC2020-04-26 19:45:50 +0000 UTC 2020-04-26 19:45:50 +0000 UTC

如何在Unity3d中序列化和反序列化json和json数组?

  • 772

我有一个使用 [WWW( https://docs.unity3d.com/ScriptReference/WWW.html )从服务器端发送的元素列表(例如,从 PHP 发送)。其内容 (WWW.text) 如下所示:

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

我正在使用的课程如下所示:

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

尝试以不同方式反序列化字符串:

  1. 使用Boomlagoon.JSON过,但由于某种原因它只检索第一个对象。
  2. 我尝试使用MiniJSON:切断[]发送的字符串然后应用库:

    IDictionary<string,object> s = Json.Deserialize(serviceData) as IDictionary<string,object>;
    foreach (KeyValuePair<string, object> kvp in s) {
        Debug.Log(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
    }
    

    但它返回 `KeyValuePair 的第一个值:

    Key = playerId, Value = 1
    Key = playerLoc, Value = Powai
    

    如果你离开括号,那么根本无法解析 json,因此foreach抛出错误是合乎逻辑的:

    NullReferenceException:对象引用未设置到对象的实例

如何正确序列化和反序列化来自 json 的数据?使用什么以及如何使用?


问题翻译https://stackoverflow.com/q/36239705/6104996

c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Алексей Шиманский
    2020-04-26T19:45:50Z2020-04-26T19:45:50Z

    从5.3.3版本开始, Unity在其 API中添加了JsonUtility 。你可以忘记各种第三方库,除非你正在做一些非常复杂的事情。

    JsonUtility比这些第三方库更快,但同时仅支持简单类型。它不支持字典等集合。例外是列表(List)。它支持列表(List)和列表数组(List array)。

    如果您需要序列化 ​​Dictionary 或做一些简单类型的简单序列化和反序列化以外的事情,请使用第三方库。否则,升级到版本 >= 5.3.3并尝试以下解决方案。

    序列化示例类:

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

    1. 一个对象(不是 JSON 数组)

    初始数据:

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

    序列化 1:

    使用public static string ToJson(object obj) 序列化为 json;.

    string playerToJson = JsonUtility.ToJson(playerInstance);
    Debug.Log(playerToJson);
    

    输出:

    {"playerId":"8484239823","playerLoc":"Powai","playerNick":"Random Nick"}
    

    连载 2:

    使用重载方法序列化为json public static string ToJson(object obj, bool prettyPrint); . 添加一个标志作为true函数的第二个参数JsonUtility.ToJson将格式化数据。将下面的输出与上面的输出进行比较。

    string playerToJson = JsonUtility.ToJson(playerInstance, true);
    Debug.Log(playerToJson);
    

    输出:

    {
        "playerId": "8484239823",
        "playerLoc": "Powai",
        "playerNick": "Random Nick"
    }
    

    反序列化 1:

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

    反序列化 2:

    使用重载方法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);
    

    反序列化 3:

    使用public static void FromJsonOverwrite(string json, object objectToOverwrite) 反序列化 json;.

    使用该方法时JsonUtility.FromJsonOverwrite,不会创建该对象的新实例,但您作为参数传递给该函数的对象将被重用,覆盖它的值。

    Player playerInstance;
    
    void Start() {
        // создаем экземпляр объекта
        playerInstance = new Player();
        deserialize();
    }
    
    void deserialize() {
        string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";    
        // Перезаписываем значения уже существующего экземпляра класса "playerInstance". Меньше затрат памяти.
        JsonUtility.FromJsonOverwrite(jsonString, playerInstance);
        Debug.Log(playerInstance.playerLoc);
    }
    

    2. 大量数据(json 数组):您的 json 包含多个带有数据的对象。

    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";
    
    // Конвертируем в 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. 修复 JsonUtility 问题:

    使用 JsonUtility.ToJson 时遇到序列化问题?您得到的是空字符串还是“ {}”?

    • 确保类不是数组。如果没有,则使用上面的帮助器类及其方法JsonHelper.ToJson代替JsonUtility.ToJson.
    • 不要忘记在[Serializable]要序列化的类的声明上方添加一个属性。
    • 从类中删除属性。例如,在变量中,public string playerId { get; set; } 删除 { get; set; }。Unity将无法序列化它们。

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

    • 如果得到Null,请确保 json 不是 json 数组。如果是这样,则使用上面的帮助器类及其方法JsonHelper.FromJson代替JsonUtility.FromJson.
    • 如果NullReferenceException在反序列化过程中获取到它,则将属性添加[Serializable]到类声明上方。

    在回答你的问题时:

    您的初始数据:

     [{"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]- 来自第三个对象的数据

    注意: 从类中删除 。如果你有,那么它将不起作用。JsonUtility不适用于声明为属性的类成员。{ get; set; }player{ get; set; }

    如果需要它们,那么您将不得不使用其他库或 XmlSerializer / BinaryFormatter


    答案翻译https://stackoverflow.com/a/36244111/6104996

    • 6
  2. DenVebber
    2020-03-21T16:14:49Z2020-03-21T16:14:49Z

    如果您对空对象有疑问,还要检查 Items 是否与代码中的所需值匹配

    [Serializable]
        private class Wrapper<T> {
            public T[] Items;
        }
    

    例如,我来自服务器的 JSON 是这样的:{"data":[{"id":"...

    因此,我们将项目更改为数据。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5