Хобрук: Ваш путь к мастерству в программировании

С# получает строку json, но не может ее десериализовать

у меня есть приложение, которое должно десериализовать массив данных, завернутый в корневой объект «результаты», используя пакет Netwonsoft.Json от NuGet

Строка Json именно такая:

{"results":[{"Coin":"SBD","LP":0.000269,"PBV":-54.36,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true},{"Coin":"XMR","LP":0.027135,"PBV":11.44,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true}]}

Эта строка Json создана из консольного приложения, которое я сделал, я хотел, чтобы оно выглядело так: https://bittrex.com/Api/v2.0/pub/market/GetTicks?marketName=BTC-NEO&tickInterval=час

Мой класс выглядит так

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

namespace WindowsFormsApp2
{
    public class Result
    {
        public string Coins { get; set; }
        public decimal LastPrice { get; set; }
        public decimal PercentBuyVolume { get; set; }
    }

    public class RootObject
    {
        public List<Result> results { get; set; }
    }
}

В основной форме у меня есть функция для загрузки с URL-адреса, который Json (у меня есть XAMPP, работающий с Apache), и десериализация его в массиве. И это выглядит так:

private void DownloadBittrexData()
        {

            int PanelID = 0;
            var Coin = new List<string>();
            var LastPrice = new List<decimal>();
            var PercentBuyVolume = new List<decimal>();
            var MACD1M = new List<bool>();
            var MACD30M = new List<bool>();
            var MACD1H = new List<bool>();
            var MACD1D = new List<bool>();

            var client = new WebClient();

            var URL = client.DownloadString("http://localhost/test.json");
            Console.WriteLine("Json String from URL: " + URL);
            var dataDeserialized = JsonConvert.DeserializeObject<RootObject>(URL);
            foreach (var data in dataDeserialized.results)
            {
                Coin.Add(data.Coins);
                LastPrice.Add(data.LastPrice);
                PercentBuyVolume.Add(data.PercentBuyVolume);

            }
            int sizeOfArrayClose = Coin.Count - 1;

            for (int i = 0; i <= sizeOfArrayClose; i++)
            {
                Console.WriteLine("Coin: " + Coin[i]);
                Console.WriteLine("Lastprice: " + LastPrice[i]);
                Console.WriteLine("PBV: " + PercentBuyVolume[i]);
            }
        }

Newtonsoft.Json конечно объявлен в начале формы вместе с System.Net

using System.Net;
using Newtonsoft.Json;

Вывод выглядит следующим образом:

Json String from URL: {"results":[{"Coin":"SBD","LP":0.000269,"PBV":-54.36,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true},{"Coin":"XMR","LP":0.027135,"PBV":11.44,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true}]}
Coin: 
Lastprice: 0
PBV: 0
Coin: 
Lastprice: 0
PBV: 0

Как будто он не может десериализовать его после загрузки. Что я должен делать? Большое спасибо.


  • JSON правильный. Какую ошибку вы получаете? 15.09.2017
  • В этой строке JSON нет полей LastPrice и PercentByVolume. У вас есть какой-то код отображения, который вы не показали, который заботится об этом? 15.09.2017
  • Нет, но я думаю, что нашел решение, благодаря Дэвиду Уоттсу. Мне нужно вызвать объект внутри public Class Result {} так же, как они вызываются в строке Json. Infact теперь вывод правильный! Json String from URL: {"results":[{"Coin":"SBD","LP":0.000269,"PBV":-54.36,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true},{"Coin":"XMR","LP":0.027135,"PBV":11.44,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true}]} Coin: SBD Lastprice: 0,000269 PBV: -54,36 Coin: XMR Lastprice: 0,027135 PBV: 11,44 Спасибо @DavidWatts e grazie mille @Piero Alberto 15.09.2017
  • Великолепно, рад, что решил это для вас. Хотите, чтобы я добавил его в качестве ответа, чтобы вы могли принять @Revengeic3. В качестве альтернативы, просто ответ «Принять транжиру», потому что в любом случае это был бы мой ответ :) 15.09.2017
  • @DavidWatts добавь! Я приму это как ответ :) 15.09.2017

Ответы:


1

Я попробовал ваш точный код в своей системе и смог получить ожидаемый результат. Надеюсь, это поможет, это легко понять.

Вот основной класс

 static void Main(string[] args)
    {

        RootObject configfile = LoadJson();

        foreach (var tResult in configfile.results)
        {
            Console.WriteLine("Coin: " + tResult.Coin);
            Console.WriteLine("Lastprice: " + tResult.LP);
            Console.WriteLine("PBV: " + tResult.PBV);
        }


        Console.ReadLine();

    }

Функция LoadJson будет

 private static RootObject LoadJson()
    {
        string json = "{\"results\":[{\"Coin\":\"SBD\",\"LP\":0.000269,\"PBV\":-54.36,\"MACD1M\":true,\"MACD30M\":true,\"MACD1H\":true,\"MACD1D\":true},{\"Coin\":\"XMR\",\"LP\":0.027135,\"PBV\":11.44,\"MACD1M\":true,\"MACD30M\":true,\"MACD1H\":true,\"MACD1D\":true}]}";



        RootObject configs = Deserialize<RootObject>(json);
        return configs;
    }

и функция Deserialize будет

private static T Deserialize<T>(string json)
    {
        T unsecureResult;
       string _DateTypeFormat = "yyyy-MM-dd HH:mm:ss";
        DataContractJsonSerializerSettings serializerSettings = new DataContractJsonSerializerSettings();
        DataContractJsonSerializer serializer;
        MemoryStream ms;
        unsecureResult = default(T);
        serializerSettings.DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat(_DateTypeFormat);

        serializer = new DataContractJsonSerializer(typeof(T));
        ms = new MemoryStream(Encoding.Unicode.GetBytes(json));

        unsecureResult = (T)serializer.ReadObject(ms);

        return unsecureResult;
    }

и теперь ваша модель данных будет

public class Result
{

    public string Coin { get; set; }
    public double LP { get; set; }
    public double PBV { get; set; }
    public bool MACD1M { get; set; }
    public bool MACD30M { get; set; }
    public bool MACD1H { get; set; }
    public bool MACD1D { get; set; }

}

public class RootObject
{
    public List<Result> results { get; set; }
}
15.09.2017

2

Имена ваших свойств не сопоставляются с именами полей в JSON. Вы можете переименовать свои свойства C#, чтобы они соответствовали JSON, но это сделает нечитаемый нижестоящий код.

Вместо этого вы должны сопоставить свои свойства (с красивыми, читаемыми именами) с именами, которые появляются в JSON, используя JsonPropertyAttribute:

public class Result
{
    public string Coin { get; set; } //didn't bother here: changed property name to Coin
    [JsonProperty("LP")]
    public decimal LastPrice { get; set; }
    [JsonProperty("PBV")]
    public decimal PercentBuyVolume { get; set; }
}
15.09.2017
  • Это то, что я хотел сказать своим комментарием к вопросу. Единственное, в чем я не уверен, так это в том, что если корпус имеет значение, то понадобится ли он и для Coin? Я когда-либо имел дело только со свойствами CamelCase JSON. 15.09.2017
  • @DavidWatts Ну, в этом случае Coin сопоставляется с Coin, а регистр сохраняется. Насколько я знаю, JSON.net сначала пытается использовать сопоставление с учетом регистра, но повторяет попытку с сопоставлением без учета регистра, если оно оказывается пустым. По всем учетным записям это не настраивается: stackoverflow.com/a/34637862/14357 15.09.2017

  • 3

    ваша модель должна быть такой для десериализации json

    public class Result
    {
        public string Coin { get; set; }
        public double LP { get; set; }
        public double PBV { get; set; }
        public bool MACD1M { get; set; }
        public bool MACD30M { get; set; }
        public bool MACD1H { get; set; }
        public bool MACD1D { get; set; }
    }
    
    public class RootObject
    {
        public List<Result> results { get; set; }
    }
    

    LastPrice and PercentBuyVolume недоступны в вашей модели, поэтому возникает ошибка.

    15.09.2017
    Новые материалы

    Решения DBA Metrix
    DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

    Начало работы с Блум
    Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...