如何将JSON反序列化为C#自定义对象的Queue集合?
游戏歌曲JSON序列化与反序列化问题解决
问题背景
我正在为开发中的游戏将歌曲数据转换为JSON对象,当前C#歌曲结构如下:
public readonly int Id = 1; public readonly int BPM = 120; public readonly string Name = "Baby's"; public readonly string Artist = "Brian"; protected Song SongFile; public Queue<NoteChart> Chart = new Queue<NoteChart>(); Chart.Enqueue(new NoteChart { gemType = 1, Key = "D", Lane = 8, beatTime = new TimeSpan(0, 0, 0, 5, 84) });
已编写部分JSON片段,但Queue<NoteChart>类型的Chart字段映射遇到困难:
{ "Id": 1, "BPM": 120, "Name": "Baby", "Artist": "Brian", "SongFile": "Songs/Baby", "Chart": { } }
请问如何正确编写Chart的JSON结构以实现反序列化为C#对象?是否有更优的实现方式?
解决方案
1. 正确的Chart JSON结构
Queue<T>本质是有序集合,JSON中用数组来表示最适配。结合NoteChart的属性,Chart的JSON结构应写成:
"Chart": [ { "gemType": 1, "Key": "D", "Lane": 8, "beatTime": "00:00:05.0840000" } ]
TimeSpan类型默认会被序列化为上述格式的字符串(主流序列化库如Newtonsoft.Json、System.Text.Json都支持这种格式的反序列化)。- 若有多条
NoteChart数据,直接在数组中追加即可。
2. 更优实现方式
(1)改用属性替代只读字段
只读字段在反序列化时可能存在赋值限制,建议将字段改为自动属性,提升序列化兼容性:
public int Id { get; set; } = 1; public int BPM { get; set; } = 120; public string Name { get; set; } = "Baby's"; public string Artist { get; set; } = "Brian"; // SongFile若需要序列化,建议改为public属性 public string SongFile { get; set; } = "Songs/Baby"; public Queue<NoteChart> Chart { get; set; } = new Queue<NoteChart>();
(2)使用DTO分离序列化与业务逻辑
创建专门的**数据传输对象(DTO)**来处理JSON序列化,与业务实体Song解耦,避免业务代码受序列化规则限制:
// 序列化用的DTO public class SongDto { public int Id { get; set; } public int BPM { get; set; } public string Name { get; set; } public string Artist { get; set; } public string SongFile { get; set; } // 用List更适配JSON数组,反序列化后再转成Queue public List<NoteChartDto> Chart { get; set; } = new List<NoteChartDto>(); } public class NoteChartDto { public int gemType { get; set; } public string Key { get; set; } public int Lane { get; set; } public TimeSpan beatTime { get; set; } } // 业务实体与DTO的映射 var songDto = JsonSerializer.Deserialize<SongDto>(jsonString); var song = new Song { Id = songDto.Id, BPM = songDto.BPM, // ...其他属性映射 Chart = new Queue<NoteChart>(songDto.Chart.Select(dto => new NoteChart { gemType = dto.gemType, Key = dto.Key, Lane = dto.Lane, beatTime = dto.beatTime })) };
(3)序列化库配置优化
- 若使用Newtonsoft.Json,可通过配置支持字段序列化、TimeSpan处理:
var settings = new JsonSerializerSettings { Formatting = Formatting.Indented, // 若仍需保留字段,开启字段序列化 IncludeFields = true, // 自定义TimeSpan格式(可选) Converters = { new TimeSpanConverter() } }; var json = JsonConvert.SerializeObject(song, settings); - 若使用System.Text.Json,需配置包含字段或使用属性:
var options = new JsonSerializerOptions { WriteIndented = true, // 若使用字段,开启字段序列化 IncludeFields = true, Converters = { new TimeSpanConverter() } }; var json = JsonSerializer.Serialize(song, options);
内容的提问来源于stack exchange,提问作者sylargaf
相关产品推荐
相关产品推荐

