Как правильно и компактно распарсить json?

127
19 ноября 2019, 06:40

Получаю от сайта ответ в формате json ( сайт ) как можно максимально компактно распарсить такой json?

{
  "BTC_BCN": {
    "BTC": "4.85852062",
    "BCN": "27783245.32186212"
  },
  "BTC_BTS": {
    "BTC": "16.16990899",
    "BTS": "1351490.36574452"
  },
  "BTC_BURST": {
    "BTC": "1.89496695",
    "BURST": "1902307.47675365"
  },
  ...

если десериализовать его, то там классов будет на 900 строк кода... Есть ли какие-нибудь другие способы? Из полученной информации от сайта хочу составить подобную таблицу

Answer 1

В общем, даю примерную наводку, как это решается.

Получение и десериализация выглядит так:

async Task Main()
{
    var data = await this.GetAsync("https://poloniex.com/public?command=return24hVolume");
    //data.Dump();
    var deserialized = JsonConvert.DeserializeObject<MyClass>(data);
    deserialized.Dump();
}
// Define other methods and classes here
public async Task<string> GetAsync(string uri)
{
    var client = new HttpClient();
    return await client.GetStringAsync(uri);
}

Это будут ваши классы описывающие структуру:

[JsonConverter(typeof(MyCustomIdConverter))]
public class MyClass
{
    public MyNode[] myNodes;
    public string totalBTC;
    public string totalETH;
    public string totalUSDC;
    public string totalUSDT;
    public string totalXMR;
    public string totalXUSD;
}
public class MyNode
{
    public string PrologTitle { get; set; }
    public string EpilogTitle { get; set; }
    public string PrologValue { get; set; }
    public string EpilogValue { get; set; }
}

(Можете переделать на key-value pair или более интересную вам структуру)

А примерно так будет выглядеть ваша обработка данных:

public class MyCustomIdConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        Type type = (Nullable.GetUnderlyingType(objectType) ?? objectType);
        bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);
        var token = JToken.Load(reader);
        if (token == null || token.Type == JTokenType.Null)
        {
            if (!isNullable)
                throw new JsonSerializationException(string.Format("Null value for type {0} at path {1}", objectType.Name, reader.Path));
            return null;
        }
        if (token.Type == JTokenType.Object)
        {
            var nodes = new List<MyNode>();
            foreach (var element in token.Children())
            {
                if(element.Type == JTokenType.Property)
                {
                    var a = (JProperty)element;
                    if(!a.Name.Contains("_"))
                    {
                        // TODO: Прочая обработка
                        continue;
                    }
                    var delimited = a.Name.Split('_');
                    var prolog_title = delimited[0];
                    var epilog_title = delimited[1];
                    var prolog = (JProperty)element.First().First();
                    var epilog = (JProperty)element.First().Last();
                    if(prolog.Name == prolog_title && epilog.Name == epilog_title)
                    {
                        var node = new MyNode {
                            PrologTitle = prolog_title,
                            EpilogTitle = epilog_title,
                            PrologValue = prolog.Value.ToString(),
                            EpilogValue = epilog.Value.ToString(),
                        };
                        nodes.Add(node);
                    }
                }
            }
            return new MyClass { myNodes = nodes.ToArray() };
        }
        throw new Exception("Вот это вот сейчас неожиданно было");
    }
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Выведет примерно такие данные:

В предметную область не вдумывался, видно, что prolog всегда BTC (можно на это доп. проверку сделать) но что это означает и какой смысл в этих данных - не знаю, поэтому можете обозвать поля как-то более осмысленно.

И да - код не содержит множества проверок, поэтому там именно логика что куда. Если вам нужна тщательная обработка ошибок и краевых случаев - её нужно будет дописать самостоятельно, это чисто концепт представлен.

PS Обработку total параметров сделайте самостоятельно, заодно и изучите тему обхода деревьев на не слишком сложных примерах.

READ ALSO
Как лучше сделать google auth

Как лучше сделать google auth

В проекте API использую google auth так:

147
Как упаковать шары в сфере?

Как упаковать шары в сфере?

Есть алгоритм для построения шаров по поверхности сферы

136
RichTextBox как пользоваться

RichTextBox как пользоваться

Подскажите пожалуйста, как пользоваться RichTextBox? Как вставлять текст и менять его внешний вид(цвет или задний фон отдельных слов и тп

122
Сделать традиционный выделенный маршрут в asp.net core

Сделать традиционный выделенный маршрут в asp.net core

Все облазил, не могу сообразить, как сделать следующее: 1Если человек в адресной строке пишет: mysite

131