C#探索之路(7):初探LitJson库并了解其中json的解析原理与处理报错

C#探索之路(7):使用LitJson库解析数据抛出的异常错误修复指南与途径Tips

对Json格式的了解程度一定程度上影响了解决JSON相关问题的效率;

1、初步较为系统的去探索LitJson

由于最初并没有系统的去了解过Json,大多都是临时看几篇文档,也正是因如此,所以才导致对Json的相关处理其实并不熟悉。

我们要做的有两步:

第一步,就是下载对应的Litjson库并导入到项目中去

第二步,就是通过库中的Json的封装形式,来构造Json对象并且做解析以便于进一步分析问题;

2、遇到的问题:

The JsonData instance has to be initialized first

3、导致的原因:

平台提供一个用json封装的string字符串,其中包含了数组类型的数据,但是在特殊的情况下,数组内容为空,客户端通过JsonData对数据进行解析后,并且对解析出来的Json对象中的数组成员进行遍历的过程中,抛出异常:

The JsonData instance has to be initialized first

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R6SLPjmL-1682480776617)(E:/LearnPath/[0006]Note/WizNote/images/image-20230423150721854.png)]

4、踩坑代码:
  • 第一种错误

    //常见的变量类型
     JsonData jsonData1 = JsonMapper.ToObject(test1String);
     JsonData json2ObjectValue1 = jsonData1["TestIntArrayList"];
     // 第一种错误尝试:
    // 报错代码:NullReferenceException: Object reference not set to an instance of an object
          foreach (JsonData o in json2ObjectValue1)
          {
              Debug.Log($"0:{o}");
          }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-34dwHM3t-1682480776618)(E:/LearnPath/[0006]Note/WizNote/images/image-20230423151135254.png)]

    第一种错误后,通常会想着谁报错,“防范谁”,通常会自以为的去判断 jsonData1 ,看到编辑器提示的那就更加确信了,实际报错的原因是因为 stirng报空了,抛出指向的报错却是Json未初始化;

    这是由于我们遍历 json2ObjectValue1.Count 时去收集了变量的信息,抛出的错误源头的异常,foreach 为空时,则停止遍历了;

    第二种错误:

    // 第二种错误尝试:
    // 报错代码:NullReferenceException: Object reference not set to an instance of an object
          if (jsonData1 !=null && json2ObjectValue1.Count > 0)
          {
              foreach (JsonData o in json2ObjectValue1)
              {
                  Debug.Log($"0:{o}");
              }
          }
    

    这个跟平台提供的字符串的结构有关,如果数组为空返回的Null,那边边界处理起来就会很清晰。但是奇怪的是我遇到的这个的情况是数组没有内容,但是JsonData又不为空。依旧还是返回了一个类的样式结构过来的时候,并且返回的字符串为“”时,边界问题处理起来就不那么清晰了,当对一个不清晰的数据进行处理的时候,就很容易遇到这种问题

    5、解决方案:

    当然解决这个问题的也很简单,对解析出来的对应的字符串判空即可,如果为了确保正确,

    则同时对josnData以及 从josnData中获取josnData[“xxxx”]变量(为string类型)判空即可解决问题;

    if(jsonData!= null && josnData["xxxx"].ToString()!=string.Empty)
    {
     ...
    }
    
6、ChatGpt会如何处理:

相信大家也看到了最近chagpt的一个热度与趋势,由于篇幅太长的原因,所以我就没有粘贴所有的代码至gpt中去一一做测试了,我便用以下代码做了一个gpt的尝试。不得不承认,在大数据语言模型里面,chatgpt确实有了一个很强大的表现力。

测试代码:

//测试常见的变量类型
        TestToJSON test1 = new TestToJSON(1, 2, 3, true);
        string test1String = JsonMapper.ToJson(test1);
        JsonData jsonData1 = JsonMapper.ToObject(test1String); 
        JsonData json2ObjectValue1 = jsonData1["TestIntArrayList"];
        foreach (JsonData o in json2ObjectValue1)
        {
            Debug.Log($"0:{o}");
        }

gpt回复1:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PwcNHr86-1682480776619)(E:/LearnPath/[0006]Note/WizNote/images/image-20230426114347077.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K7fKJIgk-1682480776619)(E:/LearnPath/[0006]Note/WizNote/images/image-20230426114358216.png)]

7、完整代码实现:
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using LitJson;
using UnityEngine;
using Debug = UnityEngine.Debug;

public class TestJsonData : MonoBehaviour
{
    void Start()
    {
        #region 1、将C#类转换成Json对象  -- ToJsonString

        //测试常见的变量类型
        TestToJSON test1 = new TestToJSON(1, 2, 3, true);
        string test1String = JsonMapper.ToJson(test1);
        Debug.Log("测试常见的变量类型::\\n通过JsonMapper包装后的字符串为:" + test1String.ToString());
        // Output:
        // {"TestbyteValue":1,"TestShortValue":2,"TestValue":3,"TestBoolValue":true,"TestIntArrayList":null,"TestCharArrayList":null,"TestStringValue":null,"Test2DIntsArrayList":null,"Test2DCharsArrayList":null,"Test2DStringsArrayList":null}

        //测试常见的字符串、数组类型
        TestToJSON test2 = new TestToJSON(new int[] {1, 1, 1}, new char[] {'2', '2', '2'}, "hello world!");
        string test2String = JsonMapper.ToJson(test2);
        Debug.Log("测试常见的字符串、数组类型::\\n通过JsonMapper包装后的字符串为:" + test2String.ToString());
        // Output:
        // {"TestbyteValue":0,"TestShortValue":0,"TestValue":0,"TestBoolValue":false,"TestIntArrayList":[1,1,1],"TestCharArrayList":["2","2","2"],"TestStringValue":"hello world!","Test2DIntsArrayList":null,"Test2DCharsArrayList":null,"Test2DStringsArrayList":null}

        //测试部分构造的常见的多维数组类型
        TestToJSON test3 = new TestToJSON(new int[][] {new[] {1, 1}, new[] {2, 2}}, new char[][] {new[] {'1', '1'}, new[] {'2', '2'}}, new string[] {"helloWorld1", "helloWorld2"});
        string test3String = JsonMapper.ToJson(test3);
        Debug.Log("测试常见的多维数组类型::\\n通过JsonMapper包装后的字符串为:" + test3String.ToString());
        // Output:
        //{"TestbyteValue":0,"TestShortValue":0,"TestValue":0,"TestBoolValue":false,"TestIntArrayList":null,"TestCharArrayList":null,"TestStringValue":null,"Test2DIntsArrayList":[[1,1],[2,2]],"Test2DCharsArrayList":[["1","1"],["2","2"]],"Test2DStringsArrayList":["helloWorld1","helloWorld2"]}

        //测试完整构造的常见的多维数组类型
        TestToJSON test4 = new TestToJSON(
            1, 2, 3, true,
            new int[] {1, 1, 1}, new char[] {'2', '2', '2'}, "hello world!",
            new int[][] {new[] {1, 1}, new[] {2, 2}}, new char[][] {new[] {'1', '1'}, new[] {'2', '2'}}, new string[] {"helloWorld1", "helloWorld2"}
        );
        string test4String = JsonMapper.ToJson(test4);
        Debug.Log("测试常见的多维数组类型::\\n通过JsonMapper包装后的字符串为:" + test4String.ToString());
        // Output:
        //{"TestbyteValue":1,"TestShortValue":2,"TestValue":3,"TestBoolValue":true,"TestIntArrayList":[1,1,1],"TestCharArrayList":["2","2","2"],"TestStringValue":"hello world!","Test2DIntsArrayList":[[1,1],[2,2]],"Test2DCharsArrayList":[["1","1"],["2","2"]],"Test2DStringsArrayList":["helloWorld1","helloWorld2"]}

        #endregion

        #region 2、将Json对象解析C#类 -- JsonToObject
        //要区分开两个情况,一种情况是对象的成员直接为Null,另一种情况是成员部位Null但成员变量值为默认null,即“”;
        // TestToJSON testArray = new TestToJSON(new int[]{});
        // string testArrayString = JsonMapper.ToJson(testArray);//先封装一遍
        // JsonData arrayJsonData = JsonMapper.ToObject(testArrayString);
        //直接解析 -- 无报错
        // if (arrayJsonData!=null )
        // {
        //     Debug.Log("arrayJsonData 不为空");
        // }
        // List<int> outputValue = new List<int>();
        // foreach (JsonData comData in arrayJsonData["TestIntArrayList"])
        // {
        //     Debug.Log("jsondata数据解析成功");
        //     outputValue.Add((int)comData);
        // }
        //间接解析 -- 没报错
        // ProtoJson Info = new ProtoJson();
        // Info.Parse(arrayJsonData);
        // List<int> testList = new List<int>();
        // if (arrayJsonData!=null)//&& Info.testData.ToString()!=string.Empty 屏蔽报错处理
        // {
        //     foreach (JsonData tag in Info.testData)
        //     {
        //         testList.Add((int) tag);
        //     }
        // }
        
        //常见的变量类型
        JsonData jsonData1 = JsonMapper.ToObject(test1String); 
        JsonData json2ObjectValue1 = jsonData1["TestIntArrayList"];
        // 第一种错误尝试:
        // 报错代码:NullReferenceException: Object reference not set to an instance of an object
         // foreach (JsonData o in json2ObjectValue1)
         // {
         //     Debug.Log($"0:{o}");
         // }
        
         // 第二种错误尝试:
         // 报错代码:NullReferenceException: Object reference not set to an instance of an object
         // if (jsonData1 !=null && json2ObjectValue1.Count > 0)
         // {
         //     foreach (JsonData o in json2ObjectValue1)
         //     {
         //         Debug.Log($"0:{(int)o}");
         //     }
         // }
         
         // 正确的解析方式:无非就是过滤,做好边界判断
         Contract.Assert(json2ObjectValue1!=null, "Json解析数据:json2ObjectValue1 为空?"); //condition:false=>halt 
         Contract.Assert(json2ObjectValue1.ToString()==null, "字符串为什么为空,请检查对应的数据");

         List<int> test = new List<int>();
         test.Add(1);
         test.Add(2);
         test.Add(3);
         test.Add(4);
         test.Add(5);
         





         #endregion

    }
}

public class TestToJSON
{
    //测试常见的变量类型
    public byte TestbyteValue;
    public short TestShortValue;
    public int TestValue;

    public bool TestBoolValue;

    //测试常见的字符串、数组类型
    public int[] TestIntArrayList;
    public char[] TestCharArrayList;
    public string TestStringValue;

    //测试常见的多维数组类型
    public int[][] Test2DIntsArrayList;
    public char[][] Test2DCharsArrayList;
    public string[] Test2DStringsArrayList;

    public TestToJSON(byte testbyteValue, short testShortValue, int testValue, bool testBoolValue)
    {
        TestbyteValue = testbyteValue;
        TestShortValue = testShortValue;
        TestValue = testValue;
        TestBoolValue = testBoolValue;
    }

    public TestToJSON(int[] testIntArrayList, char[] testCharArrayList, string testStringValue)
    {
        TestIntArrayList = testIntArrayList;
        TestCharArrayList = testCharArrayList;
        TestStringValue = testStringValue;
    }

    public TestToJSON(int[][] test2DIntsArrayList, char[][] test2DCharsArrayList, string[] test2DStringsArrayList)
    {
        Test2DIntsArrayList = test2DIntsArrayList;
        Test2DCharsArrayList = test2DCharsArrayList;
        Test2DStringsArrayList = test2DStringsArrayList;
    }

    public TestToJSON(byte testbyteValue, short testShortValue, int testValue, bool testBoolValue, int[] testIntArrayList, char[] testCharArrayList, string testStringValue, int[][] test2DIntsArrayList, char[][] test2DCharsArrayList,
        string[] test2DStringsArrayList)
    {
        TestbyteValue = testbyteValue;
        TestShortValue = testShortValue;
        TestValue = testValue;
        TestBoolValue = testBoolValue;
        TestIntArrayList = testIntArrayList;
        TestCharArrayList = testCharArrayList;
        TestStringValue = testStringValue;
        Test2DIntsArrayList = test2DIntsArrayList;
        Test2DCharsArrayList = test2DCharsArrayList;
        Test2DStringsArrayList = test2DStringsArrayList;
    }

    public TestToJSON(int[] testIntArrayList)
    {
        TestIntArrayList = testIntArrayList;
    }
}


public class ProtoJson
{
    public JsonData testData;
    
    public void Parse(JsonData JsonData)
    {
        testData = JsonData["TestIntArrayList"];
    }

}
 
8、参考链接与工具:

链接:
[1]: github:LitJson原生库
[2]: 经改造适用于Unity的LitJson库Github大佬链接
[3]: 马三改造LitJson博客
[4]: 一个Json格式验证与导出的链接
[5]: 一个Json在线格式转换的链接
[6]: 代码美化博客
在Issues中有显著提及到这个问题:The JsonData instance has to be initialized first

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2QxVtFJo-1682480776620)(E:/LearnPath/[0006]Note/WizNote/images/image-20230423145511244.png)]

公众号:平平无奇代码猴
也可以搜索:Jackiie_wang 公众号,欢迎大家关注!欢迎催更!留言!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值