简体   繁体   中英

is there any simple way to find out lowest value from json without doing de-serialization c#

I have below json output from api. I want to find out lowest value among all elements.

json data -

{
  "prices": [   
    {
      "frequency": "daily",
      "date": "2020-05-05",
      "intraperiod": false,
      "open": 295.06,
      "high": 301.0,
      "low": 294.46,
      "close": 297.56
    },
    {
      "frequency": "daily",
      "date": "2020-05-04",
      "intraperiod": false,
      "open": 289.17,
      "high": 293.69,
      "low": 112.1,
      "close": 293.16
    },
    {
      "frequency": "daily",
      "date": "2020-05-01",
      "intraperiod": false,
      "open": 286.25,
      "high": 299.0,
      "low": 222,
      "close": 289.07
    }
  ]
}

I want to compare all values among json element and display lowest value = "low": 112.1 and its own high value. "high": 293.69,

I tried like below using jquery but i want to do it in c# pls share c# code-

function get(arr, prop) {
    var min;
    for (var i=0 ; i<arr.length ; i++) {
        if (min== null || parseInt(arr[i][prop]) > parseInt(min[prop]))
            min= arr[i];
    }
    return min;
}

var min = get(arr, "low");
console.log(min.high);

You may use Newtonsoft.Json.Linq for that, parse your JSON to JObject , then get all properties with low name, find the property with lowest value and get the high value at the same level

var json = JObject.Parse(jsonString);

var properties = json.DescendantsAndSelf()
    .OfType<JProperty>()
    .Where(p => p.Name == "low");

 var lowProperty = properties
     .Aggregate((p1, p2) => p1.Value.Value<double>() < p2.Value.Value<double>() ? p1 : p2);

var highProperty = (lowProperty?.Parent as JObject)?.Property("high");
Console.WriteLine(lowProperty);
Console.WriteLine(highProperty);

It gives you

"low": 112.1
"high": 293.69

De-serializing it would be the way to go

you can de-serialize it into an object and do the calculations you want

    // <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
//    using QuickType;
//
//    var priceData = PriceData.FromJson(jsonString);

namespace QuickType
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class PriceData
    {
        [JsonProperty("prices")]
        public List<Price> Prices { get; set; }
    }

    public partial class Price
    {
        [JsonProperty("frequency")]
        public string Frequency { get; set; }

        [JsonProperty("date")]
        public DateTimeOffset Date { get; set; }

        [JsonProperty("intraperiod")]
        public bool Intraperiod { get; set; }

        [JsonProperty("open")]
        public double Open { get; set; }

        [JsonProperty("high")]
        public double High { get; set; }

        [JsonProperty("low")]
        public double Low { get; set; }

        [JsonProperty("close")]
        public double Close { get; set; }
    }

    public partial class PriceData
    {
        public static PriceData FromJson(string json) => JsonConvert.DeserializeObject<PriceData>(json, QuickType.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this PriceData self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }
}

you can use Quciktype to get POCO class from the json (The above code is from generated from that)

Then use

var data = PriceData.FromJson(json_string);
var min = data.Select(x=>x.Low).Min();
// There may be multiple Price objects with the same low, I will use the first one
min_object = data.Where(x=>x.Low == min).First()
var high_value_of_min_object = min_object.High;

You may want to decide what element you are looking for PS I have not tested the code.

You could use regex.

var pattern = "\"high\": ([0-9]+(\\.[0-9]+)?)";
MatchCollection matches = Regex.Matches(json, pattern);

var max = double.MinValue;
foreach (Match m in matches) {
    var val = Convert.ToDouble(m.Groups[1].Value);
    if (max < val) {
        max = val;
    }           
}

Same for low value.

You could create classes to represent your JSON using a tool like quicktype.io :

public partial class Temperatures
{
    [JsonProperty("prices")]
    public List<Price> Prices { get; set; }
}

public partial class Price
{
    [JsonProperty("frequency")]
    public string Frequency { get; set; }

    [JsonProperty("date")]
    public DateTimeOffset Date { get; set; }

    [JsonProperty("intraperiod")]
    public bool Intraperiod { get; set; }

    [JsonProperty("open")]
    public double Open { get; set; }

    [JsonProperty("high")]
    public double High { get; set; }

    [JsonProperty("low")]
    public double Low { get; set; }

    [JsonProperty("close")]
    public double Close { get; set; }
}

Then deserialize your json using Json.NET , and use MinBy from MoreLinq to get the minimum prices by Low . MinBy will return a IEnumerable<Price> , so we can iterate each min price and print the Low and High properties:

using Newtonsoft.Json;
using MoreLinq;

...

var deserializedJson = JsonConvert.DeserializeObject<Temperatures>(json);

var minPrices = deserializedJson.Prices.MinBy(price => price.Low);

foreach (var price in minPrices)
{
    Console.WriteLine($"Min = {price.Low}, High = {price.High}");
}

Output:

Min = 112.1, High = 293.69

Full demo on dotnetfiddle.net

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM