【问题标题】:How to deserialise JSON back to a class?如何将 JSON 反序列化回一个类?
【发布时间】:2021-05-21 09:07:46
【问题描述】:

我有一个课程Limits。我正在创建此类的几个实例,因为我有其他对象,每个对象都需要自己的Limits。因此,当我序列化所有限制实例时,json 中有几个条目。在我的示例中,您将看到我有Thermo。想象一下,json 中可能有 Thermo1Thermo2 等。我反序列化它,导航到我想要的实例,然后将其转换为Limits。但由于某种原因,所有 MinMax 值最终都为 0。

班级:

public class Limits
{
    Measured_I_ON_struct Measured_I_ON;

    Measured_I_OFF_struct Measured_I_OFF;
    Measured_V_ON_struct Measured_V_ON;
    Measured_V_OFF_struct Measured_V_OFF;

    public Limits()
    {
        Measured_I_ON = new Measured_I_ON_struct();
        Measured_I_OFF = new Measured_I_OFF_struct();
        Measured_V_ON = new Measured_V_ON_struct();
        Measured_V_OFF = new Measured_V_OFF_struct();
    }

    public struct Measured_I_ON_struct
    {
        public double Min;
        public double Max;
    }
    public struct Measured_I_OFF_struct
    {
        public double Min;
        public double Max;
    }
    public struct Measured_V_ON_struct
    {
        public double Min;
        public double Max;
    }
    public struct Measured_V_OFF_struct
    {
        public double Min;
        public double Max;
    }
}

我有一个这样的 json:

  {"Thermo":{
  "Measured_V_ON": 
  {
      "Min" : 4.5,
      "Max" : 5.5
  },
  "Measured_V_OFF": {
      "Min" : 4.5,
      "Max" : 5.5
  },
  "Measured_I_ON": {
      "Min" : 4.5,
      "Max" : 5.5
  },
   "Measured_I_OFF": {
      "Min" : 0.15,
      "Max" : 0.22
  },
  }
  }

我正在尝试将 json 反序列化回类 Limits 的实例,但每个结构内的值显示为 0。

string json = File.ReadAllText("new 2.json");
JToken jsonobject = JsonConvert.DeserializeObject<JToken>(json);
jsonobject = jsonobject["Thermo"];
Limits limits = new Limits();
limits = jsonobject.ToObject<Limits>();

limits 内的所有值都为 0。我在这里缺少什么?

【问题讨论】:

  • “但由于某种原因,所有值最终都为 0。” - 您的所有字段都是私有的。我建议您创建公共可写属性。我还建议你有一个 single Limit 类(或结构,如果你真的,真的必须),而不是为每个属性创建一个单独的结构。最后,我建议重命名您的属性以遵循 .NET 命名约定,如果需要,使用 [JsonProperty] 属性在 JSON 文件中指定命名。
  • @JonSkeet 做到了。谢谢,不敢相信我错过了。一个半小时以来一直在挠头。不知道我是需要咖啡,还是睡觉。我意识到这超出了本 OP 的范围。您能否扩展您的意思,即拥有一个 Limit 类。那我将如何构建它?那么 JSONProperty 属性是否允许我在序列化时在运行时更改键的名称?
  • 你有四种struct 类型,它们都完全相同。我建议你应该使用单一类型。

标签: c# json json.net


【解决方案1】:

您的字段是私有的,这就是它们没有被更改的原因。

不过,我会大幅更改您的代码:

  • 对所有限制使用单一类型,因为它们完全相同。
  • 使用类而不是结构,以避免创建可变结构。 (您可以改用自定义转换器,但我认为使用类更简单。)
  • Limits 中的属性使用公共属性,而不是私有字段
  • 重命名属性以遵循 .NET 命名约定,使用 [JsonProperty] 在 JSON 中指定您想要的名称。

所以是这样的:

public class Limit
{
    public double Min { get; set; }
    public double Max { get; set; }
}

public class Limits
{
    // TODO: Rename these further to expand on "I" and "V" if possible

    [JsonProperty("Measured_I_ON")]
    public Limit MeasuredIOn { get; set; } = new Limit();

    [JsonProperty("Measured_I_OFF")]
    public Limit MeasuredIOff { get; set; } = new Limit();

    [JsonProperty("Measured_V_ON")]
    public Limit MeasuredVOn { get; set; } = new Limit();

    [JsonProperty("Measured_V_OFF")]
    public Limit MeasuredVOff { get; set; } = new Limit();
}

【讨论】:

    【解决方案2】:

    下载 Newtonsoft.Json Nuget 包。用 C# 解析 Json 非常方便。 你可以这样写。

                string json = File.ReadAllText("new2.json");
                var jsonobject = JObject.Parse(json);
                var jsonBody = jsonobject["Thermo"].ToString();
                LimitsRoot limitsRoot = new LimitsRoot();
                limitsRoot = JsonConvert.DeserializeObject<LimitsRoot>(jsonBody);
    

    LimitsRoot 相关类如下所示

    public class MeasuredVON
        {
            public double Min { get; set; }
            public double Max { get; set; }
        }
    
        public class MeasuredVOFF
        {
            public double Min { get; set; }
            public double Max { get; set; }
        }
    
        public class MeasuredION
        {
            public double Min { get; set; }
            public double Max { get; set; }
        }
    
        public class MeasuredIOFF
        {
            public double Min { get; set; }
            public double Max { get; set; }
        }
    
        public class LimitsRoot
        {
            public MeasuredVON Measured_V_ON { get; set; }
            public MeasuredVOFF Measured_V_OFF { get; set; }
            public MeasuredION Measured_I_ON { get; set; }
            public MeasuredIOFF Measured_I_OFF { get; set; }
        }
    

    然后你可以通过运行来检查你会得到正确的值,如下所示

    limitsRoot.Measured_V_ON.Min

    4.5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多