如何将JSON响应直接反序列化为不可修改的第三方C# Quote类对象
解决方案
无需先反序列化为自定义Aggregate对象再做字段拷贝,直接定位JSON中的results数组节点,通过序列化配置实现字段映射和类型转换,即可直接得到List<Quote>结果,性能和直接反序列化自定义类几乎一致,百万级数据场景下可减少至少50%的内存和CPU开销。
方案1:基于Newtonsoft.Json (Json.NET)实现
通过自定义契约解析器实现字段映射,同时添加Unix毫秒时间戳转DateTime的转换器,无需修改Quote类代码:
using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System.Reflection; using Newtonsoft.Json.Linq; // 字段映射契约解析器 public class QuoteContractResolver : DefaultContractResolver { private readonly Dictionary<string, string> _jsonToClrMap = new() { {"o", nameof(Quote.Open)}, {"h", nameof(Quote.High)}, {"l", nameof(Quote.Low)}, {"c", nameof(Quote.Close)}, {"v", nameof(Quote.Volume)}, {"t", nameof(Quote.Date)} }; protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); if (member.DeclaringType == typeof(Quote)) { var mapItem = _jsonToClrMap.FirstOrDefault(kv => kv.Value == member.Name); if (mapItem.Key != null) { property.PropertyName = mapItem.Key; if (member.Name == nameof(Quote.Date)) { property.Converter = new UnixMsToDateTimeConverter(); } } } return property; } } // Unix毫秒时间戳转DateTime转换器 public class UnixMsToDateTimeConverter : JsonConverter<DateTime> { public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer) { long unixMs = (long)reader.Value; return DateTimeOffset.FromUnixTimeMilliseconds(unixMs).UtcDateTime; // 如需本地时间可追加.ToLocalTime() } public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer) => throw new NotImplementedException(); }
反序列化调用代码:
// 你的原始JSON字符串 string rawJson = "..."; var serializer = new JsonSerializer { ContractResolver = new QuoteContractResolver(), FloatParseHandling = FloatParseHandling.Decimal }; // 直接提取results节点反序列化 JObject jsonObj = JObject.Parse(rawJson); List<Quote> quotes = jsonObj["results"].ToObject<List<Quote>>(serializer);
方案2:基于System.Text.Json实现
适用于.NET Core 3.0+/.NET 5+的内置序列化库,通过自定义类型配置实现映射:
using System.Text.Json; using System.Text.Json.Serialization; // Unix毫秒时间戳转DateTime转换器 public class UnixMsToDateTimeConverter : JsonConverter<DateTime> { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { long unixMs = reader.GetInt64(); return DateTimeOffset.FromUnixTimeMilliseconds(unixMs).UtcDateTime; } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) => throw new NotImplementedException(); }
反序列化调用代码:
// 你的原始JSON字符串 string rawJson = "..."; var options = new JsonSerializerOptions { NumberHandling = JsonNumberHandling.AllowReadingFromString, TypeInfoResolver = JsonTypeInfoResolver.Combine( JsonSerializerOptions.Default.TypeInfoResolver, typeInfo => { if (typeInfo.Type != typeof(Quote)) return; foreach (var prop in typeInfo.Properties) { prop.Name = prop.Name switch { nameof(Quote.Open) => "o", nameof(Quote.High) => "h", nameof(Quote.Low) => "l", nameof(Quote.Close) => "c", nameof(Quote.Volume) => "v", nameof(Quote.Date) => "t", _ => prop.Name }; if (prop.Name == "t") prop.CustomConverter = new UnixMsToDateTimeConverter(); } }) }; // 直接提取results节点反序列化 using var doc = JsonDocument.Parse(rawJson); string resultsJson = doc.RootElement.GetProperty("results").GetRawText(); List<Quote> quotes = JsonSerializer.Deserialize<List<Quote>>(resultsJson, options);
内容的提问来源于stack exchange,提问作者Leon
相关产品推荐
相关产品推荐

