Unity问题(3)ArgumentException: JSON must represent an object type.

报错问题

ArgumentException: JSON must represent an object type.

报错截图

在这里插入图片描述

报错翻译

ArgumentException:JSON必须表示对象类型。


问题分析

Step 1 使用正确json规范

问题定位于
图中59行出现错误
判断出是对于 JsonUtility.FromJson() 理解不够导致出错。
Scripting API 在查找该方法
在这里插入图片描述
对比代码不难发现:我所用的 JsonUtility.FromJson() 返回的是一个 List 数组,而该方法签名表示返回的类型必须是一个对象。

给出我的“错误的”.json文件

错误Demo示范
[
  {
    "panelType": "ItemMessage",
    "path": "UIPanel/ItemMessagePanel"
  },

  {
    "panelType": "Knapsack",
    "path": "UIPanel/KnapsackPanel"
  },

  {
    "panelType": "MainMenu",
    "path": "UIPanel/MainMenuPanel"
  },

  {
    "panelType": "Shop",
    "path": "UIPanel/ShopPanel"
  },

  {
    "panelType": "Skill",
    "path": "UIPanel/SkillPanel"
  },

  {
    "panelType": "System",
    "path": "UIPanel/SystemPanel"
  },

  {
    "panelType": "Task",
    "path": "UIPanel/TaskPanel"
  }

]

不了解json的朋友可以先去看看这位博主关于json的文章
https://blog.csdn.net/yanqing_happy/article/details/98871448

这里我提取出要用到的部分

----JSON 语法规则-----
数据在名称/值对中
数据由逗号分隔
大括号保存对象
中括号保存数组

所以首先需要将json的语法修改为用大括号保存的对象,而不是一个数组!

修改后的json代码如下

{
  "infoList": [
    {
      "panelTypeString": "ItemMessage",
      "path": "UIPanel/ItemMessagePanel"
    },

    {
      "panelTypeString": "Knapsack",
      "path": "UIPanel/KnapsackPanel"
    },

    {
      "panelTypeString": "MainMenu",
      "path": "UIPanel/MainMenuPanel"
    },

    {
      "panelTypeString": "Shop",
      "path": "UIPanel/ShopPanel"
    },

    {
      "panelTypeString": "Skill",
      "path": "UIPanel/SkillPanel"
    },

    {
      "panelTypeString": "System",
      "path": "UIPanel/SystemPanel"
    },

    {
      "panelTypeString": "Task",
      "path": "UIPanel/TaskPanel"
    }

  ]
}


也就是用一个对象把这个数组给包装起来啦。

Step 2 使用包装类

使用 JsonUtility 序列化要支持List、Array、Dictionary 最好的方法就是使用包装类

[System.Serializable]
public class UIPanelInfo
{
    public UIPanelType panelType;
    
    public string path;

    public static UIPanelTypeJson CreateFromJSON(string jsonString)
    {
        return JsonUtility.FromJson< UIPanelTypeJson >(jsonString);
    }
}

public class UIPanelTypeJson        // UIPanelInfo 的包装类,无需加 [System.Serializable] 特性
{
    public List<UIPanelInfo> infoList;
}

想更多地了解包装类在序列化中的使用可以去看看这位博主的文章
https://blog.csdn.net/oyji1992/article/details/74505230

好,这样我们就完成了对json文件和对包装类的操作。我们可以通过UIPanelTypeJson类 生成的实例来完美地接收
JsonUtility.FromJson()返回的对象类型。

Step 3 使用ISerialiazation接口

但是还没完哦!
注意:

其中UIPanelType 是一个自定义的枚举类型
UIPanelType.cs

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

public enum UIPanelType
{
    ItemMessage,
    Knapsack,
    MainMenu,
    Shop,
    Skill,
    System,
    Task
}

此时运行unity会报出下面的错误:
在这里插入图片描述
这个问题的报错原因是我们自己定义的类型无法被Unity3D准确地序列化。

Q: 但我们又很想让自己定义的类型能够被准备的序列化,该怎么办呢?

A: 一个可行的想法是将我们的数据类型在要进行序列化时转换为Unity3D能够正确序列化的类型,而在运行时进行反序列化在转换为我们所需要的类型。

这就要用到 ISerialiazationCallbackReceiver 接口
当一个类继承该接口后则必须实现 OnBeforeSerialize() 方法和***OnAfterDeserialize()*** 方法。

OnBeforeSerialize() : Unity3D会在序列化对象之前调用该方法;
OnAfterDeserialize() : Unity3D会在序列化后调用该方法;

代码如下:

[System.Serializable]
public class UIPanelInfo:ISerializationCallbackReceiver
{
    [System.NonSerialized]
    public UIPanelType panelType;

    public string panelTypeString;      // 需要转换为 UIPanelType类型的字段,因为unity3D 支持对string类型的序列化
    public string path;

    public static UIPanelTypeJson CreateFromJSON(string jsonString)
    {
        return JsonUtility.FromJson< UIPanelTypeJson >(jsonString);
    }

    public void OnAfterDeserialize()
    {
        UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
        panelType = type;
    }

    public void OnBeforeSerialize()
    {
        
    }
}

public class UIPanelTypeJson        // UIPanelInfo 的包装类,无需加 [System.Serializable] 特性
{
    public List<UIPanelInfo> infoList;
}

OK,至此,终于解决了这个问题。花了我大半天的时间。
下面推荐一下资源,供大家学习:
bilibili:
https://www.bilibili.com/video/av17222636?p=2
https://www.bilibili.com/video/av33904479?p=23

如果有什么问题或建议,欢迎评论区一起讨论。 —— 一个刚入坑的菜鸡

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Unity "System.ArgumentException: JSON must represent an object type.\r\n at (wrapper managed-to-native) UnityEngine.JsonUtility.FromJsonInternal(string,object,System.Type)\r\n at UnityEngine.JsonUtility.FromJson (System.String json, System.Type type) [0x0005c] in <d773524469e64e608a0d15b877a002d5>:0 \r\n at UnityEngine.JsonUtility.FromJson[T] (System.String json) [0x00001] in <d773524469e64e608a0d15b877a002d5>:0 \r\n at GameConfig+<>c__DisplayClass13_0`1[T].<LoadListAsync>b__0 (UnityEngine.TextAsset asset) [0x00014] in E:\\work\\ShootingRumble\\shootingrumble\\Assets\\_Scripts\\Config\\GameConfig.cs:95 \r\n at AssetsManager+<>c__DisplayClass1_0`1[T].<LoadAssetsAsyncByLabel>b__0 (T handle) [0x00001] in E:\\work\\ShootingRumble\\shootingrumble\\Assets\\_Scripts\\Core\\Manager\\AssetsManager.cs:35 \r\n at UnityEngine.ResourceManagement.ResourceManager+<>c__DisplayClass92_0`1[TObject].<ProvideResources>b__0 (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle x) [0x00000] in E:\\work\\ShootingRumble\\shootingrumble\\Library\\PackageCache\\com.unity[email protected]\\Runtime\\ResourceManager\\ResourceManager.cs:746 \r\n at UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1+<>c__DisplayClass57_0[TObject].<add_CompletedTypeless>b__0 (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject] s) [0x00000] in E:\\work\\ShootingRumble\\shootingrumble\\Library\\PackageCache\\com.unity[email protected]\\Runtime\\ResourceManager\\AsyncOperations\\AsyncOperationBase.cs:286 \r\n at DelegateList`1[T].Invoke (T res) [0x00038] in E:\\work\\ShootingRumble\\shootingrumble\\Library\\PackageCache\\com.unity[email protected]\\Runtime\\ResourceManager\\Util\\DelegateList.cs:69 "
最新发布
06-08

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值