如何将json字符串转换为JsonObject并对其进行迭代?.NET Core 6.0 c#

3xiyfsfu  于 2022-12-01  发布在  .NET
关注(0)|答案(2)|浏览(197)

就像在主题中一样,我向一个端点发出请求,它返回给我一个json字符串。示例json字符串(选择了6个子字符串,还有大约1000个):

{"probability":0.0062596053,"tagId":"sometagid","tagName":"apple","boundingBox":{"left":0.27482307,"top":0.4361664,"width":0.14311266,"height":0.37521422}},
{"probability":0.0061301645,"tagId":"sometagid","tagName":"apple","boundingBox":{"left":0.0,"top":0.44423538,"width":0.09239961,"height":0.37426883}},
{"probability":0.0059485333,"tagId":"sometagid","tagName":"carrot","boundingBox":{"left":0.037714787,"top":0.0,"width":0.15685204,"height":0.27176687}},
{"probability":0.005887271,"tagId":"sometagid","tagName":"tomato","boundingBox":{"left":0.5249929,"top":0.70379305,"width":0.44499594,"height":0.29620594}},
{"probability":0.0057223,"tagId":"sometagid","tagName":"apple","boundingBox":{"left":0.79498,"top":0.34279144,"width":0.19351125,"height":0.39170527}},
{"probability":0.0056102676,"tagId":"sometagid","tagName":"apple","boundingBox":{"left":0.030394234,"top":0.21933028,"width":0.16375154,"height":0.3037323}},

我需要什么?我需要这个字符串被拆分成这6(+1000)个对象(最好是一个数组),我只想选择包含probability*100 > 50的对象。
我已经创建了一个类,其中包含如下值:

public class ResponseJsonNode {
    public double probability { get; set; }
    public string tagId { get; set; }
    public string tagName { get; set; }
    public BoundingBox boundingBox { get; set; }
}

BoundingBox是另一个类:

public class BoundingBox {
    double left { get; set; }
    double top { get; set; }
    double width { get; set; }
    double height { get; set; }
}

可重复的例子(好不太真的,因为我不能张贴端点和键在这里):

using System.Net;
using System.Text.Json;
using ConsoleApp1;

WebRequest request = HttpWebRequest.Create("SomeUriEndpoint");
request.Method = "POST";
request.Headers.Add("some key", "some more key");
request.Headers.Add("some content type", "some more content type");
var f = File.Open(args[0], FileMode.Open);
using (var ms = new MemoryStream()) {
    f.CopyTo(ms);
    var fileBytes = ms.ToArray();
    request.ContentLength = fileBytes.Length;
    Stream stream = request.GetRequestStream();
    stream.Write(fileBytes, 0, fileBytes.Length);
    stream.Close();
    //imageStringBase64 = Convert.ToBase64String(fileBytes);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponseAsync().Result;
string json = new StreamReader(response.GetResponseStream()).ReadToEnd();
//JsonObject jo = (JsonObject)json;
List<ResponseJsonNode> jsonNodeList = JsonSerializer.Deserialize<List<ResponseJsonNode>>(json);
foreach(ResponseJsonNode rj in jsonNodeList) {
    Console.WriteLine(rj);
}

这给了我一个错误:

The JSON value could not be converted to System.Collections.Generic.List

这也行不通:

HttpWebResponse response = (HttpWebResponse)request.GetResponseAsync().Result;
string json = new StreamReader(response.GetResponseStream()).ReadToEnd();
//JsonObject jo = (JsonObject)json;
//List<ResponseJsonNode> jsonNodeList = JsonSerializer.Deserialize<List<ResponseJsonNode>>(json);
JsonArray jsonArray = JsonNode.Parse(json).AsArray();
List<ResponseJsonNode> nodes = new List<ResponseJsonNode>();
foreach(JsonObject jo in jsonArray) {
    nodes.Add(new ResponseJsonNode { probability = Convert.ToDouble(jo["probability"]), tagName = (string)jo["tagName"] });
}
var stats = new Dictionary<string, double>();
foreach (ResponseJsonNode rjn in nodes) {
    if (rjn.probability * 100 > 50)
        if (stats.ContainsKey(rjn.tagName)) {
            stats[rjn.tagName]++;
        } else {
            stats[rjn.tagName] = 1;
        }
}

引发错误:System.InvalidOperationException: The node must be of type 'JsonArray'
我尝试过用很多教程解析它,但是每一个都似乎过时了或者不起作用(上面的例子)。那么,将json字符串转换成可迭代的JsonObject的最佳解决方案是什么呢?(不是C#库中的JsonObject类,而是我可以迭代的东西)

hc2pp10m

hc2pp10m1#

[根据上述意见中的说明进行更新。]
你显示的JSON不是数组。这就是为什么你不能将它反序列化为数组。它是一个对象,其中包含了一个数组。但是为了访问这个数组,你需要反序列化这个对象。
因此,反序列化对象。例如,使用此类:

public class ResponseObject
{
    public IEnumerable<ResponseJsonNode> predictions { get; set; }
}

您可以将对象反序列化到该类中:

ResponseJsonNode jsonNode = JsonSerializer.Deserialize<ResponseObject>(json);

基本上,你遇到的问题是理解一个对象和一个对象数组之间的区别,或者一个对象和一个对象的 * 属性 * 之间的区别。你需要理解你的数据结构,以便使用这些数据。

8mmmxcuj

8mmmxcuj2#

如果你的json是字面上你所显示的,你需要对它做一点修改,然后以标准的方式反序列化。

public class ResponseJsonNode {

    public double Probability { get; set; }
    public string TagId { get; set; }
    public string TagName { get; set; }
    public BoundingBox BoundingBox { get; set; }

    public override string ToString() =>
        $"[Node]: Probability: {Probability}; TagId: {TagId}; TagName: {TagName};\nBoundingBox: {BoundingBox}";
}

public class BoundingBox
{
    public double Left { get; set; }
    public double Top { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }

    public override string ToString() => $"[L:{Left};T:{Top};Width:{Width};Height:{Height}]";
}

反序列化,然后:

var json = GetJsonFromApi();
var trimmedJson = $"[{json.TrimEnd(',')}]";

var collection = JsonSerializer.Deserialize<List<ResponseJsonNode>>(trimmedJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));

foreach (var item in collection)
{
    Console.WriteLine($"{item}\n");
}

顺便说一句,C#命名约定建议在PascalCase中命名属性,对于从camelCase反序列化,只需使用JsonSerializerDefaults.Web选项。
我只想挑选概率 *100〉50对象。
然后简单的LINQ过滤就出现了。

相关问题