【问题标题】:Struggling to convert JSON string into an object努力将 JSON 字符串转换为对象
【发布时间】:2016-11-04 14:55:44
【问题描述】:

我正在努力解决如何将以下报价 JSON 数据转换为 C# 对象:

{"MyFeed":
{"@Provider":"SomeProvider","MMM":
    {"@name":"3M Corp","low":"194.80","high":"136.78","change":"2.80","pctchange":"0.22","ask":"135.15","bid_time":"20161104131845","bid":"134.80"}
}}

我像这样创建了一个 C# 类:

public class Quote
{
   public string Provider { get; set; }
   public Data Info { get; set; }
}

public class Data
{
  public string name { get; set; }
  public decimal low { get; set; }
  public decimal high { get; set; }
  public decimal change { get; set; }
  public decimal pctchange { get; set; }
  public decimal ask { get; set; }
  public DateTime bid_time { get; set; }
  public decimal bid { get; set; }
}

然后,在代码中,我使用HttpWebRequest 获取数据,它运行得很好。但是反序列化 JSON 数据的步骤不起作用。它不会抛出错误,只是没有数据。该代码是:

    var request = HttpWebRequest.Create(new Uri("<request URL here>")) as HttpWebRequest;
    request.Method = "POST";
    var response = request.GetResponse();
    using (Stream stream = response.GetResponseStream())
    {
        using (var reader = new StreamReader(stream))
        {
            Quote quote = JsonConvert.DeserializeObject<Quote>(reader.ReadToEnd());
            lblPrice.Text = string.Format("{0:c}", quote.Data.ask);
        }
    }

我单步执行了代码,所以我知道 Web 请求正在运行并返回一个 JSON 字符串。我只是不知道如何构造 C# 类来接受反序列化的数据。帮助将不胜感激!

【问题讨论】:

    标签: c# asp.net json json-deserialization


    【解决方案1】:

    你应该像这样定义属性。

    [JsonProperty(PropertyName = "@Provider")]
    public string Provider { get; set; }
    

    [JsonProperty(PropertyName = "@name")]
    public string name { get; set; }
    

    您还有许多其他问题,例如您的字段在 json 中不是十进制的,错误的类结构。你的班级应该是这样的:

        public class MyFeed
        {
            [JsonProperty(PropertyName = "@Provider")]
            public string Provider { get; set; }
    
            public MMM MMM { get; set; }
        }
    
        public class RootJsonObject
        {
            public MyFeed MyFeed { get; set; }
        }
    
        public class MMM
        {
            [JsonProperty(PropertyName = "@name")]
            public string name { get; set; }
            public string provider { get; set; }
            public string low { get; set; }
            public string high { get; set; }
            public string change { get; set; }
            public string pctchange { get; set; }
            public string ask { get; set; }
            public string bid_time { get; set; }
            public string bid { get; set; }
        }
    

    如何进行转换:

    RootJsonObject quote = JsonConvert.DeserializeObject<RootJsonObject>(json);
    

    【讨论】:

    • 别忘了“public Data Info { get; set; }”,看起来它的名字应该是“MMM”。
    • 我没有选择格式化 JSON 本身。它“按原样”来自第三方供应商,所以我必须忍受它。
    • @DanielAnderson 我说你的班级结构很糟糕,我重新编写它,以便它适合你从第 3 方收到的 json。
    • 谢谢。我很感激,因为这就是我一直在努力的事情! (微笑)
    【解决方案2】:

    你试过用这个json2csharp

    【讨论】:

    • 这是一个非常酷的实用程序!它生成了类结构,然后我可以根据需要重命名它的字段。非常感谢您的参考!
    【解决方案3】:
    • 使用JsonProperty 指定序列化字符串中的名称。
    • 当您传入一个包含您感兴趣的对象的对象时,您需要将整个 Quote 类型包装在不同的类型中。
    • 您需要指定DateTime 类型的序列化方式。

    这是一个完整且有效的 json 解决方案。

    class JsonTester
    {
        public void Test()
        {
            const string json = "{\"MyFeed\":{\"@Provider\":\"SomeProvider\",\"MMM\":{\"@name\":\"3M Corp\",\"low\":\"194.80\",\"high\":\"136.78\",\"change\":\"2.80\",\"pctchange\":\"0.22\",\"ask\":\"135.15\",\"bid_time\":\"20161104131845\",\"bid\":\"134.80\"}}}";
            var settings = new JsonSerializerSettings()
            {
                DateFormatString = "yyyyMMddHHmmss"
            };
            var quoteWrapper = JsonConvert.DeserializeObject<MyFeed>(json, settings);
            var quote = quoteWrapper.Quote;
        }
    }
    
    public class MyFeed
    {
        [JsonProperty("MyFeed")]
        public Quote Quote { get; set; }
    }
    
    public class Quote
    {
        [JsonProperty("@Provider")]
        public string Provider { get; set; }
        [JsonProperty(PropertyName = "MMM")]
        public Data Info { get; set; }
    }
    
    public class Data
    {
        [JsonProperty("@name")]
        public string name { get; set; }
        public decimal low { get; set; }
        public decimal high { get; set; }
        public decimal change { get; set; }
        public decimal pctchange { get; set; }
        public decimal ask { get; set; }
        public DateTime bid_time { get; set; }
        public decimal bid { get; set; }
    }
    

    【讨论】:

    • 这也很好用,我很欣赏有关确保正确解析日期的提示。
    【解决方案4】:

    您的 Quote 类应该是可序列化的。使用 DataMembers 向其添加 Serializable 属性或向其添加 DataContract 属性。

    【讨论】:

      猜你喜欢
      • 2019-08-27
      • 2020-05-27
      • 1970-01-01
      • 2018-11-21
      • 1970-01-01
      • 2011-04-23
      • 2012-06-14
      • 2012-02-20
      • 2015-01-03
      相关资源
      最近更新 更多