JSON конвертер списков C # - PullRequest
0 голосов
/ 04 июля 2018

Я полностью c # новичок. Я пытаюсь преобразовать данные JSON в C #. Я борюсь со списком. Пока я могу конвертировать основные методы, у меня есть ошибка в этом со списком. Не могли бы вы дать мне несколько советов, как решить мою проблему?

Исходные данные JSON

[{"data": {"Temperature": {"data": {"2018-07-04 13:05:00": 20.9224991798401}, "meta": {"units": "Celsius", " name ":" Temperature "," theme ":" Weather "}}}," latest ":" 2018-07-04 13:05:00 "," sensor_height ": -999," type ":" Weather ", "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) как List, который можно десериализовать из массива JSON. JsonArrayAttribute также может быть добавлен к типу, чтобы заставить его десериализовать из массива JSON.

Спасибо всем заранее.

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Есть пара проблем с вашим кодом.

  1. Поскольку JSON окружен [...], это означает, что это массив или элементы, поэтому вам нужно использовать List (или аналогичную) структуру. В вашем случае вы можете полностью отбросить класс Rootobject и десериализовать непосредственно до List<Class1>. Например:

    var result = JsonConvert.DeserializeObject<List<Class1>>(json);
    
  2. Класс Data1 использует дату в качестве имени свойства. Я бы предложил полностью удалить этот класс и изменить класс Temperature, чтобы использовать 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}");
    
0 голосов
/ 04 июля 2018

Тогда вам нужна модель. Основываясь на вашем 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...

и т. Д.

0 голосов
/ 04 июля 2018

Ваш RootObject неверен, а Class1 имеет неправильное название, но по сути это правильная структура для десериализации данных - однако данные представляют собой массив Class1. Вы можете использовать List<Class1> или 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...