Задача: получить значение "lastPriceProtected".
С мопощью ClientWebSocket получаю json, он различный:
ответ 1
{"table":"instrument","action":"update","data":[{"symbol":"XBTUSD","lastTickDirection":"ZeroMinusTick","timestamp":"2018-03-22T20:15:45.258Z"}]}
ответ 2
{"table":"instrument","action":"update","data":[{"symbol":"XBTUSD","lastPrice":8569,"lastPriceProtected":8569.7146,"lastChangePcnt":-0.0362,"timestamp":"2018-03-22T20:15:45.350Z"}]}
по этому однозначно получить значение "lastPriceProtected" не получается так как в первой строке данного параметра нет. т.е. как бы я не формировал поиск поля постоянно получаю исключение: "System.NullReferenceException: "Ссылка на объект не указывает на экземпляр объекта.""
мой код:
JObject o = JObject.Parse(str);
JToken firstProductNames = o["data"].SelectToken("lastPriceProtected");
======================================================================= после чтения документации и нескольких попыток получил рабочий код, спасибо всем кто помогал.
JObject o1 = JObject.Parse(str);
if (o1["data"] != null)
{
var firstProductNames = o1["data"].Value<JArray>().ElementAt(0).SelectToken("lastPriceProtected");
if (firstProductNames != null)
{
float value = firstProductNames.Value<float>();
Debug.WriteLine(value + "--1");
}
}
if (o1["data"] != null) проверка нужна чтобы не получать исключения.
Советую вам создать полноценную структуру данных, некий класс, где будут все возможные значения из вашего JSON
.
То есть, возьмем 2-ой JSON
и сделаем два класса:
public class Data
{
[JsonProperty("symbol")]
public string Symbol { get; set; }
[JsonProperty("lastPrice")]
public long LastPrice { get; set; }
[JsonProperty("lastPriceProtected")]
public double LastPriceProtected { get; set; }
[JsonProperty("lastChangePcnt")]
public double LastChangePcnt { get; set; }
[JsonProperty("timestamp")]
public System.DateTimeOffset Timestamp { get; set; }
}
public class Root
{
[JsonProperty("table")]
public string Table { get; set; }
[JsonProperty("action")]
public string Action { get; set; }
[JsonProperty("data")]
public Data[] Data { get; set; }
}
Как можно заметить, тут имеются все возможные значения приведенные в красивый вид с красивыми именами.
Далее нам надо десериализовать данные:
var json = JsonConvert.DeserializeObject<Root>(jsonString);
Все, можно работать. Все данные, которые имеются в JSON
- будут занесены в переменные, а те, которые пустые - будут иметь стандартные значения (то есть null
, 0
, false
и т.д.). Если не хотим путаться и не заполненные данные хотите получить в NULL
значение, то можете добавить знак ?
после типа (к примеру public double LastPriceProtected { get; set; }
меняем на public double? LastPriceProtected { get; set; }
).
Ну теперь простейший вывод:
foreach (var value in json.Data)
{
Console.WriteLine(value.LastPriceProtected); //Либо делаем проверку на необходимо на NULL/стандартное значение.
}
На выходе получим 0
, либо значение (в вашем случае это 8569,7146
).
По поводу минимализма и практичности...
1. Использование JObject
:
Маленькое приложение, где мы выводим различные данные (как в основном "теле" программы, так и в другом классе):
namespace ConsoleApp2
{
public class SumData
{
private JObject Json;
public SumData(JObject json)
{
Json = json;
}
public int Sum()
{
return (int) Json["data"]["valOne"] + (int) Json["data"]["valOne"];
}
}
class Program
{
private static JObject json;
static void Main(string[] args)
{
string jString = "...";
json = JObject.Parse(jString);
Console.WriteLine(json["Hello"]);
ListedObjects();
SumData sumData = new SumData(json);
Console.WriteLine(sumData.Sum());
Console.ReadKey();
}
private static void ListedObjects()
{
foreach (var val in json["Collection"])
{
Console.WriteLine(val["dataObject"]);
Console.WriteLine(val["dataObject2"]);
}
}
}
}
К примеру на сервере изменилась структура, все данные переименовались. Что делать? Выход - искать где крашется приложение и руками изменять все значения.
Минусы такого подхода в том, что вы не получите ошибку, пока не вызовите эти данные. То есть вы можете что то упустить при редактирование, да и кода править придется много.
Плюсы такого подхода:
Минусы:
o
, h
.2. Использование Структуры классов
:
Точно такая же задача, все точно такое же, но с классами:
namespace ConsoleApp2
{
public class RootJson
{
public string Hello { get; set; }
public Collection[] Collection { get; set; }
public Data Data { get; set; }
}
public class Collection
{
[JsonProperty("jsonServerValue")]
public int dataObject { get; set; }
public int dataObject2 { get; set; }
}
public class Data
{
public int valOne { get; set; }
public int valTwo { get; set; }
}
public class SumData
{
private RootJson Json;
public SumData(RootJson json)
{
Json = json;
}
public int Sum()
{
return Json.Data.valOne + Json.Data.valTwo;
}
}
class Program
{
private static RootJson json;
static void Main(string[] args)
{
string jString = "...";
json = JsonConvert.DeserializeObject<RootJson>(jString);
Console.WriteLine(json.Hello);
ListedObjects();
SumData sumData = new SumData(json);
Console.WriteLine(sumData.Sum());
Console.ReadKey();
}
private static void ListedObjects()
{
foreach (var val in json.Collection)
{
Console.WriteLine(val.dataObject);
Console.WriteLine(val.dataObject2);
}
}
}
}
Что имеем? Если сервер поменяет структуру, то нам достаточно поменять пару строк в нашем классе, либо вовсе с помощью [JsonProperty("...")]
мы можем указать имя переменной и нечего не трогать.
Плюсы такого подхода:
Минусы:
У вас:
"data":[{"symbol":"XBTUSD","lastPrice":8569,"lastPriceProtected":8569.7146,"lastChangePcnt":-0.0362,"timestamp":"2018-03-22T20:15:45.350Z"}]
массив, а вы пытаетесь работать как с объектом.
Надо так:
JObject o1 = JObject.Parse(str);
JToken firstProductNames = o1["data"].Value<JArray>().GetItem(0).SelectToken("lastPriceProtected");
if (firstProductNames != null) {
float value = firstProductNames.Value<float>();
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Здравствуйте, подскажите, пожалуйста, использую awesomium с помощью webview
клиент на андроиде передает multipart/form-data данные серверу на c# строковые данные извлекаются без проблем, а вот файлы разобрать не могу android использует...
Необходимо понять находится ли курсор мыши на данный момент в форме, как лучше всего это сделать?