首页 > 解决方案 > 使用 JsonTextReader 或任何其他替代方法从 json 中读取特定对象作为流

问题描述

必须将大文件作为 JSON 的一部分从 HTTP Post 读取到 Web API。因为文件本身是 JSON 的一部分。例子:

{
"type": "xxxx",
//other JSON,
 "attachment": {
    "mimetype": "text/csv",
    "extension": "csv",
    "data":{a,b,c,d,f}
} 

我只需要查找附件对象,但这里的“数据”再次包含大文件。可以是 csv、pdf、JSON 或图像,最重要的是大于 1GB。

根据分析,这些包装器能够阅读此内容

public class AttachmentParser 
             : JsonParser<Attachment>
{
    public AttachmentParser(Stream json, string jsonPropertyName)
        : base(json, jsonPropertyName)
    {
        Parse();
    }

    public override void Build(Attachment parsable, JsonTextReader reader)
    {
        if (reader.Value.Equals("extension"))
        {
            reader.Read();
            parsable.Extention = (string)reader.Value;
        }
        else if (reader.Value.Equals("data"))
        {
            reader.Read();
            parsable.Data = reader.Value;
        }
    }

    protected override bool IsBuilt(Attachment parsable, JsonTextReader reader)
    {
        var isBuilt = parsable.Extention != null && parsable.Data != null;
        return isBuilt || base.IsBuilt(parsable, reader);
    }

    private static MemoryStream SerializeToStream(object o)
    {
        MemoryStream stream = new MemoryStream();
        IFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, o);
        return stream;
    }
}

json解析器:

 public abstract class JsonParser<TParsable>
    where TParsable : class, new()
{
    private readonly Stream json;
    private readonly string jsonPropertyName;

    protected JsonParser(Stream json, string jsonPropertyName)
    {
        this.json = json;
        this.jsonPropertyName = jsonPropertyName;

        Result = new TParsable();
    }

    public TParsable Result { get; private set; }

    public abstract void Build(TParsable parsable, JsonTextReader reader);

    protected virtual bool IsBuilt(TParsable parsable, JsonTextReader reader)
    {
        return reader.TokenType.Equals(JsonToken.None);
    }

    protected void Parse()
    {
        using (var streamReader = new StreamReader(json))
        {
            using (var jsonReader = new JsonTextReader(streamReader))
            {
                do
                {
                    jsonReader.Read();
                    if (jsonReader.Value == null || !jsonReader.Value.Equals(jsonPropertyName))
                    {
                        continue;
                    }

                    var parsable = new TParsable();

                    do
                    {
                        jsonReader.r;
                    }
                    while (!jsonReader.TokenType.Equals(JsonToken.PropertyName) && !jsonReader.TokenType.Equals(JsonToken.None));

                    do
                    {
                        Build(parsable, jsonReader);
                        jsonReader.Read();
                    }
                    while (!IsBuilt(parsable, jsonReader));

                    Result = parsable;
                }
                while (!jsonReader.TokenType.Equals(JsonToken.None));
            }
        }
    }
}

查询:这里 JSONTextReader 有 jsonReader.Read() 方法,它确实逐个元素地读取,但默认情况下作为对象读取。这将在内存中,并在此操作期间增加更多的内存负载。看了看重载不包含ReadAsStream方法。

有没有办法通过不同的库或同一个库以不同的方式将大数据作为流读取(虽然没有重载)

标签: c#jsonstreamjson.netlarge-data

解决方案


推荐阅读