有啥简单的方法可以在不进行反序列化的情况下从 json 中找出最低值 c#

Posted

技术标签:

【中文标题】有啥简单的方法可以在不进行反序列化的情况下从 json 中找出最低值 c#【英文标题】:is there any simple way to find out lowest value from json without doing de-serialization c#有什么简单的方法可以在不进行反序列化的情况下从 json 中找出最低值 c# 【发布时间】:2020-08-25 00:29:50 【问题描述】:

我有以下来自 api 的 json 输出。 我想找出所有元素中的最低值。

json 数据 -


  "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
    
  ]

我想比较 json 元素中的所有值并显示最小值 = "low": 112.1 和它自己的高值。 "high": 293.69,

我尝试如下使用 jquery 但我想在 c# 中执行此操作请分享 c# 代码-

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);

【问题讨论】:

不,没有反序列化的简单方法可以做到这一点,至少反序列化为某种形式的对象结构? 哦,我明白了,你能帮我提供示例代码吗? 【参考方案1】:

您可以为此使用Newtonsoft.Json.Linq,将您的JSON解析为JObject,然后获取具有low名称的所有属性,找到值最低的属性并获取同一级别的high

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);

它给你

"low": 112.1
"high": 293.69

【讨论】:

【参考方案2】:

您可以使用正则表达式。

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;
               

同样适用于低价值。

【讨论】:

【参考方案3】:

反序列化将是要走的路

您可以将其反序列化为一个对象并进行所需的计算

    // <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 
            ,
        ;
    

你可以使用Quciktype从json中获取POCO类(上面的代码是从那个生成的)

然后使用

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;

您可能想决定要查找的元素 P.S 我没有测试过代码。

【讨论】:

【参考方案4】:

您可以使用quicktype.io 之类的工具创建类来表示您的 JSON:

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; 

然后使用Json.NET 反序列化你的json,并使用MoreLinq 中的MinBy 得到Low 的最低价格。 MinBy 将返回 IEnumerable&lt;Price&gt;,因此我们可以迭代每个最低价格并打印 LowHigh 属性:

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");

输出:

Min = 112.1, High = 293.69

dotnetfiddle.net 上的完整演示

【讨论】:

以上是关于有啥简单的方法可以在不进行反序列化的情况下从 json 中找出最低值 c#的主要内容,如果未能解决你的问题,请参考以下文章

如何让 Json.Net 在不忽略子属性的情况下从 documentDB 序列化/反序列化动态/通用对象?

如何在不创建组件的情况下从 laravel 刀片视图文件扩展 app.js 方法/数据/手表

在不使用 COM 的情况下从 C++ 调用 C# 方法

我可以在不执行合并的情况下从主干更新分支吗?

如何在不影响 Node.JS 应用程序的情况下从后台异步发送大量电子邮件?

子组件如何在不监听生命周期方法的情况下从父组件接收 props?