【问题标题】:JSON list converter C#JSON 列表转换器 C#
【发布时间】:2018-12-13 01:22:50
【问题描述】:

我完全是 C# 初学者。我正在尝试在 c# 中转换 json 数据。我在清单上苦苦挣扎。只要我能够转换基本方法,列表中就有一个错误。你介意给我一些建议如何解决我的问题吗?

原始 JSON 数据

[{“数据”:{“温度”:{“数据”:{“2018-07-04 13:05:00”:20.9224991798401},“元”:{“单位”:“摄氏度”,“名称”:“温度”,“主题”:“天气”}}},“最新”:“2018-07-04 13:05:00”,“传感器高度”:-999,“类型”:“天气”, “base_height”:-999,“geom”:{“坐标”:[-1.62469, 54.98274],“type”:“Point”},“active”:“True”,“name”:“sportshall_oat”,“source ": {"document": null, "fancy_name": "BMS", "db_name": "Bms", "third_party": false, "web_display_name": "BMS"}}]

主类

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new WebClient();

            var text = client.DownloadString("http://uoweb1.ncl.ac.uk/api/v1/sensor/live.json?sensor_name=sportshall_oat&api_key=4dopcdjiu3wtzfl32hn94hbf5ubm3q89jbh18iaxaqdzc10nlgbebqqvxqyt3ymydi59fjnyrmuqtgtdxb1sm5msac");

            Rootobject ro = JsonConvert.DeserializeObject<Rootobject>(text);
            Console.WriteLine("current time = " + ro.Property1);

            Class1 c1 = JsonConvert.DeserializeObject<Class1>(text);

            Data data = JsonConvert.DeserializeObject<Data>(text);

            Temperature temperature = JsonConvert.DeserializeObject<Temperature>(text);
            Console.WriteLine("data = " + temperature.data);

            Data1 d1 = JsonConvert.DeserializeObject<Data1>(text);

            Meta meta = JsonConvert.DeserializeObject<Meta>(text);

            Geom geom = JsonConvert.DeserializeObject<Geom>(text);

            Source source = JsonConvert.DeserializeObject<Source>(text);

         }
    }
}

JSON 数据(由 Visual Studio 生成)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{

    public class Rootobject
    {
        public Class1[] Property1 { get; set; }
    }

    public class Class1
    {
        public Data data { get; set; }
        public string latest { get; set; }
        public int sensor_height { get; set; }
        public string type { get; set; }
        public int base_height { get; set; }
        public Geom geom { get; set; }
        public string active { get; set; }
        public string name { get; set; }
        public Source source { get; set; }
    }

    public class Data
    {
        public Temperature Temperature { get; set; }
    }

    public class Temperature
    {
        public Data1 data { get; set; }
        public Meta meta { get; set; }
    }

    public class Data1
    {
        public float _20180704130500 { get; set; }
    }

    public class Meta
    {
        public string units { get; set; }
        public string name { get; set; }
        public string theme { get; set; }
    }

    public class Geom
    {
        public float[] coordinates { get; set; }
        public string type { get; set; }
    }

    public class Source
    {
        public object document { get; set; }
        public string fancy_name { get; set; }
        public string db_name { get; set; }
        public bool third_party { get; set; }
        public string web_display_name { get; set; }
    }

}

当我试图运行我的程序时,控制台被粉碎了。调试后我可以知道问题出在哪里,但我不知道如何解决它。有错误提示

Newtonsoft.Json.JsonSerializationException: '无法反序列化 当前 JSON 数组(例如 [1,2,3])转换为“ConsoleApp2.Rootobject”类型 因为该类型需要一个 JSON 对象(例如 {"name":"value"}) 正确反序列化。

要修复此错误,请将 JSON 更改为 JSON 对象(例如 {"name":"value"}) 或将反序列化类型更改为数组或 实现集合接口的类型(例如 ICollection、IList) 比如可以从 JSON 数组反序列化的 List。 JsonArrayAttribute 也可以添加到类型中以强制它 从 JSON 数组反序列化。

提前谢谢大家。

【问题讨论】:

  • JSON 周围的方括号 [] 表示它是一个数组。在这种情况下,反序列化为 List&lt;RootObject&gt; 是最常见的解决方案,所以 var ro = JsonConvert.DeserializeObject&lt;List&lt;Rootobject&gt;&gt;(text);
  • @Equalsk 更像List&lt;Class1&gt; 但是是的,基本正确:)
  • 在反序列化 JSON 之后,一旦您不需要进行任何进一步的反序列化,您就可以简单地访问初始类中的所有内容。
  • @DavidG 只是检查其他人都醒了,老实说...
  • 干得好!这是您的第一个问题,您提供了我们需要的所有相关信息来帮助您。您会惊讶于有多少人在第一次尝试时无法做到这一点!

标签: c# json visual-studio list


【解决方案1】:

您的RootObject 是错误的,Class1 的名称很糟糕,但它本质上是反序列化数据的正确结构 - 但是数据是 Class1 的数组。您可以使用 List&lt;Class1&gt;Class1[] (数组) - 两者都应该工作:

var client = new WebClient();
var text = client.DownloadString("http://uoweb1.ncl.ac.uk/api/v1/sensor/live.json?sensor_name=sportshall_oat&api_key=4dopcdjiu3wtzfl32hn94hbf5ubm3q89jbh18iaxaqdzc10nlgbebqqvxqyt3ymydi59fjnyrmuqtgtdxb1sm5msac");
var result = JsonConvert.DeserializeObject<List<Class1>>(text);

您不需要单独反序列化所有子部分,例如您可以这样做:

var name = result[0].name;

(注意:您的列表只有一个项目,因此您需要向列表询问索引为 0 的项目,然后是您所追求的任何属性)

我不会重复有关您的 Temperature 课程的警告,但请参阅 @DavidG's answer

【讨论】:

  • 感谢您的回复。我仍然不确定最后一行“var name = result.name;” .你介意解释一下我应该写什么而不是“名称”来显示控制台内的数据吗?我试图调用温度方法来显示温度,但我收到错误消息“温度”不是 Class1 的一部分
  • @Monika 这只是为了证明一旦反序列化,您就可以读取任何属性。要获得Temperature,它在Data 类中,所以result.data.Temperature。要写入控制台,您可以使用非常直观命名的 Console.WriteLine(result.data.Temperature); 方法。希望有帮助
  • 好的,这就是我试图运行的。我写了 var temp = result.data.Temperature;然后是 Console.WriteLine(temp);但是“数据”这个词被错误突出显示:“列表”不包含“数据”的定义,并且可以找到接受“列表”类型的第一个参数的扩展方法“数据”(您是否缺少 using 指令或程序集引用?)
  • 哦,对不起,我的错。您的列表有 1 项。 var temp = result[0].data.Temperature;@Monika
  • 好吧,这是有道理的。所以我期待看到当前日期和温度的输出,但唯一的输出是“ConsoleApp2.Temperature”。是不是说明我的 JSON 数据类写错了?
【解决方案2】:

您的代码存在一些问题。

  1. 由于 JSON 被 [...] 包围,这意味着它是一个数组或项,因此您需要使用 List(或类似的)结构。在您的情况下,您可以完全删除 Rootobject 类并直接反序列化为 List&lt;Class1&gt;。例如:

    var result = JsonConvert.DeserializeObject<List<Class1>>(json);
    
  2. Data1 类使用日期作为属性名称。我建议完全删除该类并修改Temperature 类以使用Dictonary&lt;DateTime, float&gt;

    public class Temperature
    {
        public Dictionary<DateTime, float> data { get; set; }
        public Meta meta { get; set; }
    }
    

    现在您可以处理传入的任何DateTime,您可以像这样使用它:

    var data = obj[0].data.Temperature.data;
    Console.WriteLine($"The temperature on {data.Key} was {data.Value}");
    

【讨论】:

  • Temperature 班级的好电话!
  • 感谢您的建议,我按照您的建议更改了课程。
  • @Monika 没问题。不要忘记投票并接受您认为合适的答案。哦,很高兴在纽卡斯尔认识另一个人!
  • 很遗憾我不能投票,因为我的声誉低于 15 分。很高兴认识!
  • @Monika 您可以选择对您最有帮助的答案旁边的勾号(我建议这个是正确的!)。那不是投票标记已接受的(对您而言)答案。
【解决方案3】:

那么你需要一个模型。根据您的 JSON,它会产生类似这样的结果。

public class RootObject
{
    public Data data { get; set; }
    public DateTime latest { get; set; }
    public int sensor_height { get; set; }
    public string type { get; set; }
    public int base_height { get; set; }
    public Geom geom { get; set; }
    public string active { get; set; }
    public string name { get; set; }
    public Source source { get; set; }
}

public class Data
{
    public Temperature Temperature { get; set; }
    public Meta meta { get; set; }
}

public class Geom
{
    public float[] coordinates { get; set; }
    public string type { get; set; }
}

public class Source
{
    Public string document { get; set; }
    Public string fancy_name { get; set; }
    Public string db_name { get; set; }
    Public string third_party { get; set; }
    Public string web_display_name { get; set; }
}

public class Temperature 
{
    public string data { get; set; }
}

public class Meta
{
    Public string units { get; set; }
    Public string name { get; set; }
    Public string theme { get; set; }
}

创建模型后,您只需使用它即可。

var result = JsonConvert.DeserializeObject<RootObject>(your_json_string);

然后你可以像这样访问对象:

result.data..
result.latest...

等等。

【讨论】:

  • 这不起作用,原因与 OP 存在实际问题的原因完全相同
  • 而且你的代码还是和原来的代码一样的问题。看前面2个答案
猜你喜欢
  • 1970-01-01
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多