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
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}"); }
第一种错误后,通常会想着谁报错,“防范谁”,通常会自以为的去判断 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:
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