Unity Newtonsoft JsonConvert序列化整数自动转float问题咨询
问题说明
- 场景:Unity中使用NewtonSoft.JsonConvert实现.xls文件转.json文件功能
- 存储结构:使用
List<Dictionary<string, object>>存储Excel解析后的数据,包含类似<"ID", 1001>的整数值键值对 - 异常现象:调用
JsonConvert.SerializeObject序列化后,整数值被自动转换为浮点型,输出内容为"ID": 1001.0,\r\n - 需求:序列化后保留整数原始类型,若原始值为整数1001,最终生成的json文件中对应值为1001而非1001.0
- 当前实现代码:
string json = JsonConvert.SerializeObject (table); JsonPath = "Assets/Plugins/ExcelToJson/Spreadsheet2.json"; using (FileStream fileStream=new FileStream(JsonPath,FileMode.Create,FileAccess.Write)) { using (TextWriter textWriter = new StreamWriter(fileStream, encoding)) { textWriter.Write (json); } }
问题原因
Excel解析单元格数值时,默认会将所有数字类型读取为double类型存入Dictionary的object值中,Newtonsoft.Json序列化double类型的整数值时,不会自动做整数类型判定,会默认按浮点格式输出,因此会出现.0后缀。
解决方案
方案1:序列化阶段自定义数值转换器(侵入性最低)
自定义Json转换器,序列化时判断double值是否为整数,是则按整数格式输出,否则走默认浮点序列化逻辑。
- 新增自定义转换器类:
using Newtonsoft.Json; using System; public class IntactNumberConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(object); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value is double doubleVal) { // 判定当前double值是否为整数 if (Math.Abs(doubleVal % 1) < double.Epsilon) { writer.WriteValue((long)doubleVal); return; } } // 非整数值、非double类型走默认序列化逻辑 serializer.Serialize(writer, value); } public override bool CanRead => false; public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } }
- 修改序列化代码,传入自定义转换器:
// 序列化时挂载自定义转换器 string json = JsonConvert.SerializeObject(table, new IntactNumberConverter()); JsonPath = "Assets/Plugins/ExcelToJson/Spreadsheet2.json"; using (FileStream fileStream=new FileStream(JsonPath,FileMode.Create,FileAccess.Write)) { using (TextWriter textWriter = new StreamWriter(fileStream, encoding)) { textWriter.Write (json); } }
方案2:Excel读取阶段修正数值类型(根源解决)
在解析Excel单元格内容时就做类型判定,将整数值直接存储为int/long类型,浮点值保留double/float类型,后续无需修改序列化逻辑即可正常输出。
参考处理逻辑:
// 读取Excel单元格后做类型转换 object cellValue = currentCell.Value; if (cellValue is double numValue) { // 判定为整数则转成long类型存储 if (Math.Abs(numValue % 1) < double.Epsilon) { cellValue = (long)numValue; } } // 将处理后的cellValue存入Dictionary即可
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

