在 C#
中,Newtonsoft.Json
是处理 JSON 数据的常用库,它提供了丰富的功能来序列化和反序列化对象。为了有效地使用它,理解如何处理不同的数据类型至关重要。本文将详细说明如何使用 Newtonsoft.Json
进行类型转换,以及如何处理复杂的自定义类型。
目录
1. 基础类型的转换
Newtonsoft.Json
提供了对基本数据类型的直接转换,例如字符串、整数、布尔值、浮点数等。你可以使用 JsonConvert.SerializeObject()
和 JsonConvert.DeserializeObject<T>()
来处理这些基本类型。
示例:
int number = 123;
string json = JsonConvert.SerializeObject(number);
Console.WriteLine(json); // 输出: 123
int result = JsonConvert.DeserializeObject<int>(json);
Console.WriteLine(result); // 输出: 123
对于基础类型,Newtonsoft.Json
会自动根据 JSON 的格式推断类型。
2. 复杂类型的转换
对于自定义类或者对象,Newtonsoft.Json
可以轻松进行序列化和反序列化,将对象转换为 JSON 字符串,或者从 JSON 字符串转换为对象。
示例:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
var person = new Person { Name = "John", Age = 30 };
string json = JsonConvert.SerializeObject(person);
Console.WriteLine(json); // 输出: {"Name":"John","Age":30}
Person deserializedPerson = JsonConvert.DeserializeObject<Person>(json);
Console.WriteLine(deserializedPerson.Name); // 输出: John
在序列化复杂类型时,Newtonsoft.Json
会根据类的属性生成 JSON 键值对。
3. 匿名类型的转换
Newtonsoft.Json
允许序列化匿名类型,但反序列化时必须指定目标类型。
示例:
var anonymousObject = new { Name = "Alice", Age = 25 };
string json = JsonConvert.SerializeObject(anonymousObject);
Console.WriteLine(json); // 输出: {"Name":"Alice","Age":25}
匿名类型可以轻松序列化,但反序列化时需要明确指定类型。
4. 动态类型的转换
使用 Newtonsoft.Json
时,你可以使用 dynamic
来处理不确定的 JSON 结构。JObject
和 JArray
也可以用于动态操作 JSON 数据。
示例:
string json = @"{ 'Name': 'David', 'Age': 28 }";
dynamic obj = JsonConvert.DeserializeObject<dynamic>(json);
Console.WriteLine(obj.Name); // 输出: David
JObject jObject = JObject.Parse(json);
Console.WriteLine(jObject["Name"]); // 输出: David
动态类型适合处理复杂或不确定结构的 JSON 数据。
5. 枚举类型的转换
Newtonsoft.Json
可以将枚举序列化为整数或字符串。通过使用 StringEnumConverter
,你可以控制枚举值是以字符串还是数字的形式序列化。
示例:
public enum Gender
{
Male,
Female,
Other
}
public class Person
{
public string Name { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }
}
var person = new Person { Name = "Eve", Gender = Gender.Female };
string json = JsonConvert.SerializeObject(person);
Console.WriteLine(json); // 输出: {"Name":"Eve","Gender":"Female"}
Person deserializedPerson = JsonConvert.DeserializeObject<Person>(json);
Console.WriteLine(deserializedPerson.Gender); // 输出: Female
枚举的序列化可以通过 StringEnumConverter
来控制为字符串格式。
6. 字典和集合类型的转换
Newtonsoft.Json
也能处理字典和集合类型(如 List<T>
、Dictionary<K,V>
)。这些类型的序列化结果通常是 JSON 数组或对象。
示例:
var people = new List<Person>
{
new Person { Name = "John", Age = 30 },
new Person { Name = "Jane", Age = 25 }
};
string json = JsonConvert.SerializeObject(people);
Console.WriteLine(json); // 输出: [{"Name":"John","Age":30},{"Name":"Jane","Age":25}]
var deserializedPeople = JsonConvert.DeserializeObject<List<Person>>(json);
Console.WriteLine(deserializedPeople[0].Name); // 输出: John
对于字典,Newtonsoft.Json
会将其序列化为键值对的 JSON 对象。
字典示例:
var dictionary = new Dictionary<string, int>
{
{ "apple", 1 },
{ "banana", 2 }
};
string json = JsonConvert.SerializeObject(dictionary);
Console.WriteLine(json); // 输出: {"apple":1,"banana":2}
var deserializedDictionary = JsonConvert.DeserializeObject<Dictionary<string, int>>(json);
Console.WriteLine(deserializedDictionary["apple"]); // 输出: 1
7. 自定义对象的转换
有时,你可能需要自定义对象的序列化和反序列化行为。你可以通过继承 JsonConverter
来实现自定义转换器。
示例:
public class CustomDateConverter : JsonConverter<DateTime>
{
private readonly string _dateFormat = "yyyy-MM-dd";
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString(_dateFormat));
}
public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return DateTime.ParseExact((string)reader.Value, _dateFormat, null);
}
}
public class Event
{
public string Title { get; set; }
[JsonConverter(typeof(CustomDateConverter))]
public DateTime Date { get; set; }
}
var newEvent = new Event { Title = "Conference", Date = new DateTime(2024, 1, 15) };
string json = JsonConvert.SerializeObject(newEvent);
Console.WriteLine(json); // 输出: {"Title":"Conference","Date":"2024-01-15"}
var deserializedEvent = JsonConvert.DeserializeObject<Event>(json);
Console.WriteLine(deserializedEvent.Date.ToString("yyyy-MM-dd")); // 输出: 2024-01-15
自定义转换器可以灵活控制序列化和反序列化过程。
8. 自定义转换器 (JsonConverter
)
自定义转换器允许你精确控制对象如何转换为 JSON 或从 JSON 转换为对象。继承 JsonConverter
并实现 WriteJson()
和 ReadJson()
方法。
创建自定义转换器的步骤:
- 创建一个继承自
JsonConverter
的类。 - 重写
CanConvert
方法以指定该转换器处理的类型。 - 重写
WriteJson
和ReadJson
方法以自定义序列化和反序列化逻辑。
9. 处理转换中的常见问题
类型不匹配
当 JSON 数据与目标类型不匹配时,JsonConvert
会抛出异常。常见的错误包括:
- JSON 属性的类型与类属性不一致。
- 缺少必需的 JSON 属性。
解决方法:
- 使用
[JsonProperty]
指定属性名称映射。 - 使用
JsonSerializerSettings.MissingMemberHandling
配置如何处理缺失成员。
循环引用问题
当对象存在循环引用时,序列化可能会导致无限递归。你可以通过设置 ReferenceLoopHandling
来避免此问题。
示例:
var settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string json = JsonConvert.SerializeObject(yourObject, settings);
10. 总结
Newtonsoft.Json
提供了强大的序列化和反序列化功能,可以处理 C# 中各种类型的数据,包括基础类型、复杂对象、枚举、集合和字典。通过自定义转换器,你可以进一步控制数据转换的行为。理解和灵活运用这些功能,有助于在 C# 项目中高效地处理 JSON 数据。