使用 System.Text.Json Utf8JsonReader 从大 JSON 反序列化我需要的值

Deserializing values I need from large JSON using System.Text.Json Utf8JsonReader

我正在尝试执行以下操作..

在 POCO

中不代表 JSON

使用 Utf8JsonReader 仅查找并反序列化隐藏在大型 JSON 深处的特定 属性 的值。

筛选 JSON 个令牌:有效

以下是有效的代码。

using System;
using System.IO;
using System.Text;
using System.Text.Json;
namespace ProcessData
{
    class Program
    {

        private static readonly byte[] s_pagetypeUtf8 = Encoding.UTF8.GetBytes("type");
        private static readonly byte[] s_transactionorderidUtf8 = Encoding.UTF8.GetBytes("orderid");
        private static readonly byte[] s_transactionorderamountUtf8 = Encoding.UTF8.GetBytes("amount_to_pay");

static void Main(string[] args)
        {
            string fileName = "D:\500GBNP\Projects\temp1\temp1.json";
            using var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            using var sr = new StreamReader(fs, Encoding.UTF8);
            string line = String.Empty;
            bool success =false;
            string orderid="";
            decimal orderamount=0;
            while ((line = sr.ReadLine()) != null)
                {
                    ReadOnlySpan<byte> jsonReadOnlySpan = Encoding.UTF8.GetBytes(line);
            
                    var reader = new Utf8JsonReader(jsonReadOnlySpan);

                    while (reader.Read())
                    {
                        JsonTokenType tokenType = reader.TokenType;

                        switch (tokenType)
                        {
                            case JsonTokenType.PropertyName:
                                if (reader.ValueTextEquals(s_pagetypeUtf8))
                                {
                                    // Assume valid JSON, known schema
                                    reader.Read();
                                    if (reader.GetString().Equals("Success Confirmation"))
                                    {
                                        success=true;
                                        
                                    
                                    }
                                }
                                break;
                        }
                    }
                }
            Console.WriteLine($"{success}");
        }

    }
}

json 文件包含以下文本并且能够成功找到该行是否包含页面类型值 Success Confirmation :

{"contexts":{"page":{"type":"Success Confirmation"},"transaction":{"orderid":100002210,"shipping_cost":70,"subtotal":200,"subtotal_incl_tax":200,"tax_cost":0,"amount_to_pay":270,"delivery":{"postcode":"400666","state":"West Bengal","city":"kolkata","country":"IN"},"billing":{"postcode":"400666","state":"West Bengal","city":"kolkata","country":"IN"},"product_details":{"no_of_items":1,"order_items":[{"name":"Designer Red Folral Earrings with White Beads","id":5384,"quantity":1,"price":200,"tax":0,"price_incl_tax":200,"actual_price":400,"percent_discount":50,"category":["New Arrivals","Modern Jewellery","Women","Earrings & Studs","Earrings & Studs","Danglers","View All","Hot Deals","Puja Collection 2016"]}]},"payment_mathod":"Cash On Delivery"}}

我需要做的是如果页面类型是成功确认,获取orderid的值和amount_to_pay。 这就是我卡住的地方。

我尝试了以下..

if (reader.GetString().Equals("Success Confirmation"))
                                    {
                                        success=true;
                                        reader.Read(); 
                                        if (reader.TokenType == JsonTokenType.EndObject)
                                            {
                                                break;
                                            }
                                            reader.Read();
                                        if (reader.ValueTextEquals(s_transactionorderidUtf8))
                                            {
                                                reader.Read();
                                                orderid=reader.GetString();
                                            }

                                        if (reader.ValueTextEquals(s_transactionorderamountUtf8))
                                            {
                                                reader.Read();
                                                orderamount=reader.GetDecimal();
                                            }
                                    Console.WriteLine($"{orderid}:{orderamount}");
                                    
                                    }

如果没有 if (reader.TokenType == JsonTokenType.EndObject) 代码块,它会抛出错误

> Cannot compare the value of a token type 'EndObject' to text.

有了代码块,它就向前移动了

真诚感谢任何帮助。

如果我无法解释或您需要任何进一步的信息,请务必询问。

谢谢

What I need to do is if page type is Success Confirmation, get the value of orderid and amount_to_pay.

我觉得你想多了。您可以只映射 类:

class Order {
    public Context contexts { get;set;}
};

class Context {
    public Page page {get; set;}
    public Transaction transaction {get; set;}
}

class Page {
    public string type {get; set;}
}

class Transaction 
{
    public long orderid {get;set;}
    public decimal amount_to_pay {get;set;}
}

然后

var o = JsonSerializer.Deserialize<Order>(json);

Console.WriteLine(o.contexts.page.type);
Console.WriteLine(o.contexts.transaction.orderid);
Console.WriteLine(o.contexts.transaction.amount_to_pay);

结果是:

Success Confirmation
100002210
270

选项 B. JsonDocument

如果您不想创建 类,那么您可以使用 JsonDocument

using JsonDocument doc = JsonDocument.Parse(json);

var context = doc.RootElement.GetProperty("contexts");
Console.WriteLine(context.GetProperty("page").GetProperty("type").GetString());
Console.WriteLine(context.GetProperty("transaction").GetProperty("orderid").GetUInt64());
Console.WriteLine(context.GetProperty("transaction").GetProperty("amount_to_pay").GetDecimal());

结果:

Success Confirmation
100002210
270