内存中压缩JSON对象?14MB JSON加载占360MB内存求优化方案
优化JSON加载的内存占用问题
嘿,这个问题我太熟了——14MB的JSON加载成JObject居然占了360MB内存,这其实是Json.NET(Newtonsoft.Json)用动态JToken树的典型副作用,每个JObject/JProperty都带着一堆元数据,内存开销自然爆炸。给你几个实用的优化方向:
一、调整Json.NET的配置减少内存开销
你当前的代码用了默认的JsonSerializer配置,很多不必要的功能会额外占用内存,可以关闭这些选项:
- 关闭类型名称处理:默认情况下Json.NET可能会保留类型信息(哪怕你没用到),添加这行:
serializer.TypeNameHandling = TypeNameHandling.None; - 禁用日期自动解析:如果你的JSON里没有日期字符串,关闭日期解析能避免不必要的对象创建:
serializer.DateParseHandling = DateParseHandling.None; - 使用
JsonLoadSettings忽略冗余信息:加载JObject时传入配置,忽略注释和行信息,减少额外内存占用:JObject data = JObject.Load(red, new JsonLoadSettings { CommentHandling = CommentHandling.Ignore, LineInfoHandling = LineInfoHandling.Ignore });
二、替换为强类型模型(最有效!)
JObject是动态结构,每个属性都要存储额外的元数据(比如属性名、类型信息等),换成强类型类能直接砍掉这些冗余开销,内存占用会大幅下降。
首先根据你的JSON结构定义模型:
public class OrderValidationData { public int Count { get; set; } public string Name { get; set; } public List<string> Keys { get; set; } public Dictionary<string, OrderDetail> Data { get; set; } } public class OrderDetail { public decimal MinimalNetPrice { get; set; } public decimal VatRate { get; set; } }
然后修改加载代码,直接反序列化到强类型模型:
public static void Load(string path = CacheFilePath) { path = Path.GetFullPath(path); if (!File.Exists(path)) return; JsonSerializer serializer = new JsonSerializer(); using (FileStream s = File.Open(path, FileMode.Open)) using (StreamReader sr = new StreamReader(s)) using (JsonReader red = new JsonTextReader(sr)) { var validationData = serializer.Deserialize<OrderValidationData>(red); // 这里使用validationData即可 } }
这种方式的内存占用会接近JSON本身的大小(加上对象的基本开销),远低于360MB。
三、换用System.Text.Json(.NET Core/.NET 5+)
如果你用的是较新的.NET版本,微软官方的System.Text.Json在内存效率上比Json.NET的JObject更优,尤其是配合强类型模型使用:
public static void Load(string path = CacheFilePath) { path = Path.GetFullPath(path); if (!File.Exists(path)) return; var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; using (FileStream s = File.Open(path, FileMode.Open)) { var validationData = JsonSerializer.Deserialize<OrderValidationData>(s, options); // 使用数据 } }
它的底层用Utf8处理,避免了额外的字符串转换,内存开销更小。
四、流式处理(如果不需要全量数据)
如果你的业务不需要把整个JSON都留在内存里,可以在读取时逐个处理条目,比如遍历Data里的每个订单详情,处理完就释放,不过看你的结构可能需要全量数据,这个作为备选方案。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

