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

如何将JSON反序列化为TypeScript的Map<TKey, TValue>实例?

如何将JSON反序列化为真正的Map<TKey, TValue>实例

JSON本身没有Map的原生表示,JSON.parse只会返回普通对象或数组,因此必须手动将解析后的对象转换为Map实例。以下是几种实用的实现方式:

1. 基础转换法(适用于简单键类型)

如果JSON是{"key1":"value1","key2":"value2"}这类字符串键结构,直接用Object.entries配合Map构造函数即可:

const jsonStr = '{"id":1,"name":"test"}';
const parsedObj = JSON.parse(jsonStr);
const map = new Map<string, any>(Object.entries(parsedObj));

// 可正常调用Map的所有方法
map.forEach((value, key) => {
  console.log(`${key}: ${value}`);
});

若键为数字类型,JSON解析后会转为字符串,需手动转换键类型:

const map = new Map<number, string>(
  Object.entries(parsedObj).map(([key, value]) => [parseInt(key, 10), value])
);

2. 自定义reviver函数(利用JSON.parse内置参数)

通过JSON.parse的第二个参数reviver,可在解析过程中直接将目标结构转为Map,适合嵌套场景中区分普通对象和Map:

function mapReviver(key: string, value: any): any {
  // 假设JSON中用"__type": "Map"标记需要转换的结构
  if (typeof value === 'object' && value !== null && value.__type === 'Map') {
    return new Map(Object.entries(value.data));
  }
  return value;
}

// 对应的JSON需提前添加类型标记
const jsonWithMap = '{"config": {"__type": "Map", "data": {"theme": "dark", "fontSize": 14}}}';
const result = JSON.parse(jsonWithMap, mapReviver);
// result.config 是真正的Map实例

3. TypeScript泛型工具函数(保证类型安全)

封装泛型函数,确保转换后的Map类型符合预期,同时支持自定义键类型转换:

function jsonToMap<TKey extends string | number | symbol, TValue>(
  jsonStr: string,
  keyConverter?: (key: string) => TKey
): Map<TKey, TValue> {
  const parsed = JSON.parse(jsonStr);
  const entries = Object.entries(parsed).map(([key, value]) => {
    const convertedKey = keyConverter ? keyConverter(key as string) : (key as unknown as TKey);
    return [convertedKey, value as TValue];
  });
  return new Map(entries);
}

// 数字键示例
const numMap = jsonToMap<number, string>('{"1":"a","2":"b"}', key => parseInt(key, 10));
// 字符串键示例
const strMap = jsonToMap<string, number>('{"age":25,"score":90}');

4. 递归转换(处理嵌套Map结构)

如果JSON存在多层嵌套的Map,可通过递归函数批量处理:

function deepJsonToMap(obj: any): any {
  if (typeof obj !== 'object' || obj === null) return obj;
  // 识别标记字段转换为Map
  if (obj.__type === 'Map') {
    return new Map(Object.entries(obj.data).map(([k, v]) => [k, deepJsonToMap(v)]));
  }
  if (Array.isArray(obj)) {
    return obj.map(item => deepJsonToMap(item));
  }
  return obj;
}

// 使用示例
const nestedJson = '{"user": {"__type": "Map", "data": {"name": "Alice", "settings": {"__type": "Map", "data": {"notifications": true}}}}}';
const result = deepJsonToMap(JSON.parse(nestedJson));
// result.user 和 result.user.get('settings') 均为Map实例

性能与C#配合建议

  • 转换后的Map可直接利用Map.forEach的性能优势,无需每次遍历都调用Object.entries;数据量极大时优先用基础转换法,减少额外函数调用开销。
  • 由于你主要使用C#,序列化时可自定义JSON转换器(如Newtonsoft.Json或System.Text.Json),给Map/Dictionary类型字段添加__type标记,方便前端自动识别转换。例如C#中System.Text.Json的自定义转换器:
public class MapConverter<TKey, TValue> : JsonConverter<Dictionary<TKey, TValue>>
{
    public override Dictionary<TKey, TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, Dictionary<TKey, TValue> value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteString("__type", "Map");
        writer.WriteStartObject("data");
        foreach (var kvp in value)
        {
            JsonSerializer.Serialize(writer, kvp.Key, options);
            JsonSerializer.Serialize(writer, kvp.Value, options);
        }
        writer.WriteEndObject();
        writer.WriteEndObject();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:25:01