UD3L6——Newtonsoft.Json

Newtonsoft.Json

Newtonsoft.Json​,通常也被称为 Json.NET,是一个非常流行的用于处理 JSON 数据的高性能 .NET 库。
它由 James Newton-King 开发,并广泛应用于各种 .NET 应用程序中,以实现对象与 JSON 之间的序列化和反序列化。

官网:Json.NET - Newtonsoft

官方文档:Json.NET Documentation

关于 Newtonsoft.Json​ 进阶用法可以参考此视频:分享一些Newtonsoft.Json的实用功能与技巧_哔哩哔哩_bilibili

导入 Newtonsoft.Json

Newtonsoft.Json 已经提供了针对 Unity 的定制版本,因此,将 Newtonsoft.Json 导入到 Unity 项目非常简单
直接通过 Package Manager 即可导入 Newtonsoft.Json,此版本为 IL2CPP 做了优化,因此直接使用此版本即可

image

使用 Newtonsoft.Json 序列化

JsonConvert.SerializeObject()​ 是 Newtonsoft.Json 提供的序列化方法

  • 参数一:要序列化的对象
  • 参数二:Formatting​ 枚举,如果传入 Formatting.Indented​ 则返回的 Json 是有换行和缩进(两个空格)形式的
  • 返回值:序列化出来的 Json 字符串

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using UnityEngine;
using Newtonsoft.Json;
using System.Collections.Generic;

public class JsonTest : MonoBehaviour
{
void Start()
{
// 初始化数据类
JsonDataTest test = new()
{
hp = 1,
sex = false,
speed = 16.66f,
resName = "Airplane/Airplane1",
subData = new() { testInt = 1, testFloat = 2 },
TestNull = null,
subDatas = new SubData[]
{
new() { testInt = 10, testFloat = 1.1111f },
new() { testInt = 20, testFloat = 22.222f },
new() { testInt = 30, testFloat = 333.33f },
},
subDataDic = new Dictionary<string, SubData>()
{
{ "Lihua", new() { testInt = 100, testFloat = -1.0f } },
{ "xiaohong", new() { testInt = 200, testFloat = -2.0f } },
}
};

// 序列化类,不换行
string json1 = JsonConvert.SerializeObject(test);
Debug.Log($"Json without Format: \n{json1}");
// 序列化类,换行带缩进
string json2 = JsonConvert.SerializeObject(test, Formatting.Indented);
Debug.Log($"Json with Format: \n{json2}");
}
}

public class JsonDataTest
{
public int hp;
public bool sex;
public float speed;
public string resName;
public SubData subData;
public SubData TestNull;
public SubData[] subDatas;
public Dictionary<string, SubData> subDataDic;
}

public class SubData
{
public int testInt;
public float testFloat;
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Json without Format: 
{"hp":1,"sex":false,"speed":16.66,"resName":"Airplane/Airplane1","subData":{"testInt":1,"testFloat":2.0},"TestNull":null,"subDatas":[{"testInt":10,"testFloat":1.1111},{"testInt":20,"testFloat":22.222},{"testInt":30,"testFloat":333.33}],"subDataDic":{"Lihua":{"testInt":100,"testFloat":-1.0},"xiaohong":{"testInt":200,"testFloat":-2.0}}}


Json with Format:
{
"hp": 1,
"sex": false,
"speed": 16.66,
"resName": "Airplane/Airplane1",
"subData": {
"testInt": 1,
"testFloat": 2.0
},
"TestNull": null,
"subDatas": [
{
"testInt": 10,
"testFloat": 1.1111
},
{
"testInt": 20,
"testFloat": 22.222
},
{
"testInt": 30,
"testFloat": 333.33
}
],
"subDataDic": {
"Lihua": {
"testInt": 100,
"testFloat": -1.0
},
"xiaohong": {
"testInt": 200,
"testFloat": -2.0
}
}
}

序列化注意事项

  • 默认情况下,Newtonsoft.Json 只会序列化公共属性和字段。若要序列化私有成员变量,则需要为私有变量添加特性 [JsonProperty]

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    using UnityEngine;
    using Newtonsoft.Json;

    public class JsonTest : MonoBehaviour
    {
    void Start()
    {
    PrivateFieldTest test = new("AAA", "BBB");

    string json = JsonConvert.SerializeObject(test);
    Debug.Log(json);
    }
    }

    public class PrivateFieldTest
    {
    string test1;
    [JsonProperty] string test2;

    public PrivateFieldTest(string test1, string test2)
    {
    this.test1 = test1;
    this.test2 = test2;
    }
    }

    输出:

    1
    {"test2":"BBB"}
  • 支持字典类型,但是字典的键最好是字符串,基本类型也可以使用,如果使用复杂类型,必须提供相应的序列化和反序列化转换逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    Dictionary<string, int> stringKeyData = new()
    {
    { "One", 1 },
    { "Two", 2 },
    { "Three", 3 },
    };

    Dictionary<float, int> floatKeyData = new()
    {
    { 1.1f, 1 },
    { 2.2f, 2 },
    { 3.3f, 3 },
    };

    string json1 = JsonConvert.SerializeObject(stringKeyData);
    Debug.Log(json1);
    string json2 = JsonConvert.SerializeObject(floatKeyData);
    Debug.Log(json2);

    // 非字符串键反序列化测试
    var test = JsonConvert.DeserializeObject<Dictionary<float, int>>(json2);
    foreach (var item in test)
    {
    Debug.Log($"Key: {item.Key}, Value: {item.Value}");
    }

    输出:

    image

  • Newtonsoft.Json 可以准确的保存 null​ 类型

使用 Newtonsoft.Json 反序列化

JsonConvert.DeserializeObject()​ 是 Newtonsoft.Json 提供的反序列化方法

  • 参数一:要反序列化的 Json 字符串
  • 返回值:反序列化得到的实例

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using Newtonsoft.Json;
using System.Collections.Generic;
using UnityEngine;

public class JsonTest : MonoBehaviour
{
string json = @"{""testInt"":999,""testFloat"":999.9}";
string arrayJson = @"
[
{""testInt"":1,""testFloat"":10.1},
{""testInt"":2,""testFloat"":20.2},
{""testInt"":3,""testFloat"":30.3}
]";
string listJson = @"
[
{""testInt"":1, ""testFloat"":10.1},
{""testInt"":2,""testFloat"":20.2},
{""testInt"":3,""testFloat"":30.3}
]";

void Start()
{
// 假设从外部拿到了Json字符串,分别反序列化实例对象、对象数组、对象列表
var data1 = JsonConvert.DeserializeObject<SubData>(json);
var data2 = JsonConvert.DeserializeObject<SubData[]>(arrayJson);
var data3 = JsonConvert.DeserializeObject<List<SubData>>(listJson);
// 输出查看反序列化正确与否
Debug.Log($"Data: TestInt: {data1.testInt}, TestFloat: {data1.testFloat}");
Debug.Log("Array Test: ");
for (int i = 0; i < data2.Length; i++)
{
Debug.Log($"[{i}]: TestInt: {data2[i].testInt}, TestFloat: {data2[i].testFloat}");
}
Debug.Log("List Test: ");
for (int i = 0; i < data3.Count; i++)
{
Debug.Log($"[{i}]: TestInt: {data3[i].testInt}, TestFloat: {data3[i].testFloat}");
}
}
}

public class SubData
{
public int testInt;
public float testFloat;
}

输出:

image

反序列化注意事项

  • 支持字典类型,字典的键最好是字符串,如果是其他基本类型则要确保字符串转换不会出错,如果使用复杂类型,必须提供反序列化转换逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    Dictionary<string, int> stringKeyData = new()
    {
    { "One", 1 },
    { "Two", 2 },
    { "Three", 3 },
    };

    Dictionary<float, int> floatKeyData = new()
    {
    { 1.1f, 1 },
    { 2.2f, 2 },
    { 3.3f, 3 },
    };

    string json1 = JsonConvert.SerializeObject(stringKeyData);
    Debug.Log(json1);
    string json2 = JsonConvert.SerializeObject(floatKeyData);
    Debug.Log(json2);

    // 非字符串键反序列化测试
    var test = JsonConvert.DeserializeObject<Dictionary<float, int>>(json2);
    foreach (var item in test)
    {
    Debug.Log($"Key: {item.Key}, Value: {item.Value}");
    }

    输出:

    image

  • Newtonsoft.Json 对自定义类不要求有无参构造

  • Newtonsoft.Json 可以直接读取数据集合,可以反序列化到数组或者列表内