You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET+RemObjects环境下,JSON序列化如何强制浮点字段保留末尾零?

实现Oxygene中Nullable字段JSON序列化保留至少两位小数

方案一:使用自定义JavaScriptConverter(原生JavaScriptSerializer)

由于System.Web.Script.Serialization.JavaScriptSerializer默认不会保留浮点数字的末尾零,我们可以通过实现自定义转换器来控制序列化逻辑。注意:JSON数字类型本身不区分小数位数,此方案会将浮点值转为字符串类型以保留两位小数格式。

1. 定义自定义转换器

MyTypeConverter = public class(System.Web.Script.Serialization.JavaScriptConverter)
public
  method Serialize(obj: System.Object; serializer: System.Web.Script.Serialization.JavaScriptSerializer): System.Collections.Generic.IDictionary<string, System.Object>; override;
  method Deserialize(dictionary: System.Collections.Generic.IDictionary<string, System.Object>; type: System.Type; serializer: System.Web.Script.Serialization.JavaScriptSerializer): System.Object; override;
  method GetSupportedTypes(): System.Collections.Generic.IEnumerable<System.Type>; override;
end;

implementation

method MyTypeConverter.GetSupportedTypes(): System.Collections.Generic.IEnumerable<System.Type>;
begin
  Result := new List<System.Type>([typeof(MyType)]);
end;

method MyTypeConverter.Serialize(obj: System.Object; serializer: System.Web.Script.Serialization.JavaScriptSerializer): System.Collections.Generic.IDictionary<string, System.Object>;
var
  myTypeObj: MyType;
  dict: Dictionary<string, Object>;
begin
  myTypeObj := obj as MyType;
  dict := new Dictionary<string, Object>();
  
  if myTypeObj.valueD.HasValue then
    // 格式化为两位小数的字符串
    dict.Add('valueD', myTypeObj.valueD.Value.ToString("F2"))
  else
    dict.Add('valueD', null);
    
  Result := dict;
end;

method MyTypeConverter.Deserialize(dictionary: System.Collections.Generic.IDictionary<string, System.Object>; type: System.Type; serializer: System.Web.Script.Serialization.JavaScriptSerializer): System.Object;
var
  myTypeObj: MyType;
  valueStr: string;
  valueD: Double;
begin
  myTypeObj := new MyType();
  
  if dictionary.ContainsKey('valueD') and (dictionary['valueD'] <> null) then
  begin
    valueStr := dictionary['valueD'] as string;
    if Double.TryParse(valueStr, valueD) then
      myTypeObj.valueD := valueD;
  end;
  
  Result := myTypeObj;
end;

2. 使用转换器序列化

var 
  data: MyType;
  s: string;
  serializer: System.Web.Script.Serialization.JavaScriptSerializer;

begin
  data := new MyType;
  data.valueD := 1.9;

  serializer := new System.Web.Script.Serialization.JavaScriptSerializer();
  serializer.Converters.Add(new MyTypeConverter());
  s := serializer.Serialize(data);

  // 结果: {"valueD": "1.90"}
end;

方案二:改用Newtonsoft.Json(输出数字类型的1.90)

如果需要保留数字类型同时显示两位小数格式,JavaScriptSerializer无法实现,建议使用功能更强大的Newtonsoft.Json库。

1. 定义自定义数字转换器

MyDoubleConverter = public class(Newtonsoft.Json.JsonConverter)
public
  method CanConvert(objectType: Type): Boolean; override;
  method WriteJson(writer: Newtonsoft.Json.JsonWriter; value: Object; serializer: Newtonsoft.Json.JsonSerializer); override;
  method ReadJson(reader: Newtonsoft.Json.JsonReader; objectType: Type; existingValue: Object; serializer: Newtonsoft.Json.JsonSerializer): Object; override;
end;

implementation

method MyDoubleConverter.CanConvert(objectType: Type): Boolean;
begin
  Result := objectType = typeof(System.Nullable<Double>) or objectType = typeof(Double);
end;

method MyDoubleConverter.WriteJson(writer: Newtonsoft.Json.JsonWriter; value: Object; serializer: Newtonsoft.Json.JsonSerializer);
var
  d: Double;
begin
  if value = null then
  begin
    writer.WriteNull();
    exit;
  end;
  
  d := Double(value);
  // 直接写入格式化后的数字字符串,保留两位小数
  writer.WriteRawValue(d.ToString("F2"));
end;

method MyDoubleConverter.ReadJson(reader: Newtonsoft.Json.JsonReader; objectType: Type; existingValue: Object; serializer: Newtonsoft.Json.JsonSerializer): Object;
var
  d: Double;
begin
  if reader.Value = null then
  begin
    if objectType = typeof(System.Nullable<Double>) then
      Result := null
    else
      Result := 0.0;
    exit;
  end;
  
  Double.TryParse(reader.Value.ToString(), d);
  Result := d;
end;

2. 序列化对象

var 
  data: MyType;
  s: string;
  settings: Newtonsoft.Json.JsonSerializerSettings;

begin
  data := new MyType;
  data.valueD := 1.9;

  settings := new Newtonsoft.Json.JsonSerializerSettings();
  settings.Converters.Add(new MyDoubleConverter());
  
  s := Newtonsoft.Json.JsonConvert.SerializeObject(data, settings);

  // 结果: {"valueD": 1.90}
end;

关键说明

  • JSON的数字类型本身不保留小数位数,1.9和1.90在JSON语义中完全等价,解析后的值均为1.9。
  • 若仅需输出字符串格式的两位小数,使用方案一;若需输出数字类型且显示两位小数,必须使用方案二这类支持自定义数字格式化的序列化库。

内容的提问来源于stack exchange,提问作者wBB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 15:45:10