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

如何在Delphi中反序列化C++ std::multimap生成的JSON至TDictionary<double,string>

在Delphi中用mORMot将数字键JSON对象反序列化为TDictionary<double, string>

针对你遇到的问题,这里提供两种可行的解决方案,分别适用于简单解析场景和复杂结构体自动反序列化场景:

方法1:手动遍历JSON对象键值对

这种方式直接高效,无需额外配置,适合单独解析目标JSON节点的场景:

uses
  SysUtils, Generics.Collections, mORMot.Json;

function JsonObjToDoubleStringDict(const AJsonObj: TJSONObject): TDictionary<double, string>;
var
  LPair: TJSONPair;
  LKey: double;
begin
  Result := TDictionary<double, string>.Create;
  try
    for LPair in AJsonObj do
    begin
      if TryStrToFloat(LPair.JsonString.Value, LKey) then
        Result.Add(LKey, LPair.JsonValue.Value);
    end;
  except
    Result.Free;
    raise;
  end;
end;

// 使用示例
var
  LJson: TJSONValue;
  LSomeObj: TJSONObject;
  LDict: TDictionary<double, string>;
begin
  LJson := TJSON.ParseJSONValue('{"name":"mark","data":[1,2,3,4],"some":{"11.1":"Hello","22.2":"","44.4":"World"}}');
  try
    LSomeObj := LJson.GetValue<TJSONObject>('some');
    LDict := JsonObjToDoubleStringDict(LSomeObj);
    try
      // 遍历输出字典内容示例
      for var KVP in LDict do
        Writeln(Format('%.1f: %s', [KVP.Key, KVP.Value]));
    finally
      LDict.Free;
    end;
  finally
    LJson.Free;
  end;
end;

方法2:注册mORMot自定义序列化器

如果需要在复杂结构体的自动反序列化中直接映射该类型,可以给TDictionary<double, string>注册自定义序列化逻辑:

uses
  SysUtils, Generics.Collections, mORMot, mORMot.Json, mORMot.Core.JSON;

// 封装字典类型以便注册(mORMot对泛型类直接注册可能存在限制)
type
  TDoubleStringDict = class(TDictionary<double, string>)
  end;

// 注册自定义序列化/反序列化逻辑
procedure RegisterDoubleStringDictSerializer;
begin
  TJSONSerializer.RegisterCustomSerializer(TDoubleStringDict,
    // 序列化逻辑(可选,若需要将字典转回JSON)
    procedure(const Obj: TObject; out Value: TJSONValue)
    var
      LDict: TDoubleStringDict;
      LObj: TJSONObject;
      KVP: TPair<double, string>;
    begin
      LDict := TDoubleStringDict(Obj);
      LObj := TJSONObject.Create;
      try
        for KVP in LDict do
          LObj.AddPair(FloatToStr(KVP.Key), KVP.Value);
        Value := LObj;
      except
        LObj.Free;
        raise;
      end;
    end,
    // 反序列化逻辑
    procedure(const Value: TJSONValue; Obj: TObject)
    var
      LDict: TDoubleStringDict;
      LObj: TJSONObject;
      LPair: TJSONPair;
      LKey: double;
    begin
      LDict := TDoubleStringDict(Obj);
      LObj := Value as TJSONObject;
      LDict.Clear;
      for LPair in LObj do
      begin
        if TryStrToFloat(LPair.JsonString.Value, LKey) then
          LDict.Add(LKey, LPair.JsonValue.Value);
      end;
    end);
end;

// 定义对应完整结构体
type
  TMyData = class
  public
    name: string;
    data: TArray<integer>;
    some: TDoubleStringDict;
    constructor Create;
    destructor Destroy; override;
  end;

constructor TMyData.Create;
begin
  inherited;
  some := TDoubleStringDict.Create;
end;

destructor TMyData.Destroy;
begin
  some.Free;
  inherited;
end;

// 使用示例
var
  LJsonStr: string;
  LMyData: TMyData;
begin
  RegisterDoubleStringDictSerializer;
  LJsonStr := '{"name":"mark","data":[1,2,3,4],"some":{"11.1":"Hello","22.2":"","44.4":"World"}}';
  LMyData := TJSONSerializer.JsonToObject<TMyData>(LJsonStr);
  try
    // 输出结构体中字典的内容
    for var KVP in LMyData.some do
      Writeln(Format('Key: %.1f, Value: %s', [KVP.Key, KVP.Value]));
  finally
    LMyData.Free;
  end;
end;

注意事项

  1. 由于JSON键本质是字符串,转换double时需注意格式兼容性(如小数点分隔符,若需支持非英文区域可传入TFormatSettings参数);
  2. 若原C++ std::multimap存在重复的double键,TDictionary无法存储重复键,此时需改用TList<TPair<double, string>>等支持重复键的结构,并调整对应解析逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:47:35