4

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

原始 JSON 数据

[{“数据”:{“温度”:{“数据”:{“2018-07-04 13:05:00”:20.9224991798401},“元”:{“单位”:“摄氏度”,“名称”: “温度”,“主题”:“天气”}}},“最新”:“2018-07-04 13:05:00”,“传感器高度”:-999,“类型”:“天气”,“基地高度” :-999,“geom”:{“坐标”:[-1.62469, 54.98274],“类型”:“点”},“活动”:“真”,“名称”:“sportshall_oat”,“来源”:{ “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 数组反序列化。JsonArrayAttribute 也可以添加到类型中以强制它从 JSON 数组反序列化。

谢谢大家。

4

3 回答 3

3

你的代码有几个问题。

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

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

    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}");
    
于 2018-07-04T15:06:39.787 回答
3

RootObject错了,而且Class1名字很糟糕,但它本质上是反序列化数据的正确结构 - 但是数据是Class1's 的数组。您可以使用 a List<Class1>or Class1[](array) - 任何一个都应该工作:

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;

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

我不会重复有关您Temperature班级的警告,但请参阅@DavidG 的回答

于 2018-07-04T15:03:42.633 回答
-2

然后你需要一个模型。根据您的 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...

等等。

于 2018-07-04T15:14:09.070 回答