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

如何将JSON反序列化为带非字符串(如FileInfo)键的Dictionary

问题描述

我编写了一段测试代码,尝试实现Dictionary<FileInfo, Point>的序列化与反序列化往返操作,但始终无法成功:

using System.Drawing;
using Newtonsoft.Json;

namespace JSON_Trials;

class StackExample {
    public static void Main() {
        Dictionary<FileInfo, Point> dict_write = new() {
            {new("a_file_name.txt"), new(1, 2)},
        };

        var json_write = JsonConvert.SerializeObject(dict_write);
        File.WriteAllText("_dict.json", json_write);

        var json_read = File.ReadAllText("_dict.json");
        var dict_read = JsonConvert.DeserializeObject<Dictionary<FileInfo, Point>>(json_read);
        Console.WriteLine(dict_read.Count);
    }
}

运行时抛出如下错误:

Newtonsoft.Json.JsonSerializationException: 'Could not convert string 'a_file_name.txt' to dictionary key type 'System.IO.FileInfo'. Create a TypeConverter to convert from the string to the key type object. Path '['a_file_name.txt']', line 1, position 19.'

生成的JSON内容为:

{"a_file_name.txt":"1, 2"}

我尝试编写了多个TypeConverter、JsonConverter、ContractResolver实现,但均未生效。FileInfo本身带有单字符串构造函数,JSON格式也是标准的字典结构,理论上应该不难实现,到底遗漏了什么?是否存在可行方案?

场景限制

  • 字典的Key是带单字符串构造函数的对象类型(例如FileInfo(string filename))
  • Key类型不可修改(无法修改源码、添加注解)
  • JSON格式必须保持不变(不可改为数组形式)
  • Value类型不影响实现逻辑

环境:.NET 7 & C# 11


解决方案

最终采用的代码如下(感谢@Serg),这里选用FullName作为序列化的键值,因为它更接近唯一标识符:

using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using Newtonsoft.Json;

namespace JSON_Trials;

class StackExample {
    public static void Main() {
        Dictionary<FileInfo, Point> dict_write = new() {
            {new("a_file_name.txt"), new(1, 2)},
        };

        TypeDescriptor.AddAttributes(typeof(FileInfo), new TypeConverterAttribute(typeof(FileInfoTypeConverter)));

        var json_write = JsonConvert.SerializeObject(dict_write);
        File.WriteAllText("_dict.json", json_write);

        var json_read = File.ReadAllText("_dict.json");
        var dict_read = JsonConvert.DeserializeObject<Dictionary<FileInfo, Point>>(json_read);
        Console.WriteLine(dict_read.Count);
    }
}

internal class FileInfoTypeConverter : TypeConverter {
    public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) {
        if (sourceType == typeof(string))
            return true;
        return base.CanConvertFrom(context, sourceType);
    }

    public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) {
        if (value is string str)
            return new FileInfo(str);
        return base.ConvertFrom(context, culture, value);
    }

    public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) {
        if (value is FileInfo fi)
            return fi.FullName;
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

内容的提问来源于stack exchange,提问作者Xan-Kun Clark-Davis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:50:25