【问题标题】:Json.Net serializing the class name instead of the internal propertiesJson.Net 序列化类名而不是内部属性
【发布时间】:2015-12-01 13:14:20
【问题描述】:

这是代码:

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"
    },
    ...

如 cmets 中所述,预期行为是将 Name 和 TypeName 写入 json,而不是类的名称。

【问题讨论】:

  • 那么你的意图是什么?
  • @TheVillageIdiot 预期的行为是其参数的seralizytion,也就是说,类似于{"Name": "myName", "TypeName": "typeName"}
  • 什么是ParametersParameterDictionary的成员有哪些?请先阅读minimal reproducible example
  • @ArghyaC 由于Parameters类被正确序列化,我认为没有必要在帖子中描述它。此外,它是一个令人讨厌的遗产代码,不会为当前的问题提供太多帮助。我希望这会有所帮助。
  • @ArghyaC 好的,现在我明白了。如果真的没关系,我可以写 string 或其他任何东西让任何人复制代码并将其粘贴到他们的 IDE 中。我要编辑帖子。

标签: c# json.net


【解决方案1】:

您看到此行为的原因是因为您使用复杂对象 (HydroObjectIdentifier) 作为字典中的键。在 JSON 中,对象键必须始终是字符串,根据 the spec。当 Json.Net 尝试序列化字典时,它会看到您的键是 not 字符串。因为它需要一个字符串,所以它只是在你的类上调用ToString()。 C# 中ToString() 的默认实现返回类型的名称,在您的情况下为RSEngine.HydroObjectIdentifier

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

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

  1. 为您的标识符类实现TypeConverter,如Json.Net Serialization Guide 中所述。有关详细信息,请参阅 MSDN 中的 How to: Implement a Type Converter。实现类型转换器后,您需要使用 [TypeConverter] 属性标记您的类,以便 Json.Net 知道使用它。
  2. 对字典使用自定义的JsonConverter,这会改变键值对写入 JSON 的方式。有关该方法的示例,请参阅 How To Serialize a class that derives from a Dictionary

【讨论】:

  • 这是我一直在寻找的答案。非常详细和清晰,谢谢。我改变了我的选择并将其标记为已接受的答案。作为旁注:我不太明白为什么这个问题被否决了,因为我认为你的回答表明这个问题并非微不足道。我在问之前做了我的研究,很难找到可以导致解决方案的关键词。再次感谢您抽出宝贵的时间来回答,我希望答案能帮助其他寻找相同解决方案的人。
  • 很高兴我的回答对您有所帮助。至于为什么这个问题被否决,谁能说?我觉得这是一个合理的问题。我不会担心太多。
【解决方案2】:

尝试重写 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;
    }

}

【讨论】:

  • 这当然可以。关于在这种特殊情况下为什么需要这样做的任何想法?我在相当多的项目中使用过Json.Net,这是我第一次遇到这个问题。
  • @XavierPeña 这是因为您将对象用作字典中的键。我添加了一个更详细地解释这一点的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
相关资源
最近更新 更多