Json.Net正在序列化类名,而不是内部属性

本文关键字:内部 属性 Net 序列化 Json | 更新日期: 2023-09-27 18:25:09

这是代码:

public class ParameterDictionary : Dictionary<HydroObjectIdentifier, string>
{
    public void WriteToJson(string jsonFilePath)
    {
        string json = Newtonsoft.Json.JsonConvert.SerializeObject(this, formatting: Newtonsoft.Json.Formatting.Indented);
        System.IO.File.WriteAllText(jsonFilePath, json);
    }
}
public struct HydroObjectIdentifier
{
    public string Name { get; set; }
    public string TypeName { get; set; }
    public HydroObjectIdentifier(string name, string typeName)
    {
        this.Name = name;
        this.TypeName = typeName;
    }
}

这就是Json的结果。请注意,它显示的是类名RSEngine.HydroObjectIdentifier,而不是它的参数,这在我的代码中是不需要的。

{
  "RSEngine.HydroObjectIdentifier": [
    {
      "myString"
    },
    ...

正如注释中所解释的,预期的行为是将Name和TypeName写入json,而不是类的名称。

Json.Net正在序列化类名,而不是内部属性

您之所以看到这种行为,是因为您正在使用复杂对象(HydroObjectIdentifier)作为Dictionary中的键。在JSON中,根据规范,对象键必须始终是字符串。当JSON.Net尝试序列化字典时,它会发现您的键是而不是字符串。由于它需要一个字符串,所以它只是在类上调用ToString()。C#中ToString()的默认实现返回类型的名称,在您的情况下是RSEngine.HydroObjectIdentifier

如果你实现了自己的ToString()方法,正如另一个答案中所建议的那样,那么你可以制作出你想绕过这个问题的任何密钥。然而,这种方法的缺点是,您将无法将JSON反序列化回字典中。这是因为Json.Net无法使用converse"FromString"方法将序列化键从字符串转换回标识符类。如果您需要能够使用JSON进行完整的往返(序列化和反序列化),那么您将需要一个不同的解决方案。

Json.Net中有几种可能的方法来处理复杂的字典键:

  1. 为您的标识符类实现TypeConverter,如Json.Net Serialization Guide中所述。有关详细信息,请参阅MSDN中的"如何:实现类型转换器"。在实现了类型转换器之后,您将需要用[TypeConverter]属性标记您的类,以便Json.Net知道如何使用它
  2. 为字典使用自定义的JsonConverter,它可以更改键值对写入JSON的方式。有关该方法的示例,请参阅如何序列化从Dictionary派生的类

尝试覆盖ToString()方法:

public struct HydroObjectIdentifier
{
    public string Name { get; set; }
    public string TypeName { get; set; }
    public override string ToString()
    {
        return Newtonsoft.Json.JsonConvert.SerializeObject(this);
    }
    public HydroObjectIdentifier(string name, string typeName)
    {
        this.Name = name;
        this.TypeName = typeName;
    }
}