首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Newtonsoft Json.Net -反序列化时如何有条件地添加(或跳过)数组中的项?

Newtonsoft Json.Net -反序列化时如何有条件地添加(或跳过)数组中的项?
EN

Stack Overflow用户
提问于 2021-10-11 10:04:24
回答 1查看 217关注 0票数 1

我正在寻找一种性能优化的解决方案,我正试图为一些使用金融市场订单簿的代码找到合适的解决方案,基本上,我要返回的JSON对象有一个数组类型的属性,包含数百/数千个订单对象,但是我只对其中的10到20个对象感兴趣(需要动态确定)。从性能的角度来看,我更愿意跳过反序列化&在添加了所需的项之后添加数组中的每个项。为了澄清,它总是数组中我实际需要的前10到20项,这之后的一切都可以被排除在外。

在Json.NET中有实现这一目标的方法吗?我一直在看JsonConverters,但搞不懂。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-11 17:22:35

您可以创建以下JsonConverter<T []>,它将跳过数组条目,超出一定数量:

代码语言:javascript
复制
public class MaxLengthArrayConverter<T> : JsonConverter<T []>
{
    public MaxLengthArrayConverter(int maxLength) => this.MaxLength = maxLength >= 0 ? maxLength : throw new ArgumentException(nameof(maxLength));

    public int MaxLength { get; }

    public override T [] ReadJson(JsonReader reader, Type objectType, T [] existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
            return null;
        reader.AssertTokenType(JsonToken.StartArray);
        var list = new List<T>();
        while (reader.ReadToContentAndAssert().TokenType != JsonToken.EndArray)
        {
            if (list.Count < MaxLength)
                list.Add(serializer.Deserialize<T>(reader));
            else
                reader.Skip();
        }
        return list.ToArray();
    }

    public override bool CanWrite => false;
    public override void WriteJson(JsonWriter writer, T [] value, JsonSerializer serializer) => throw new NotImplementedException();
}

public static partial class JsonExtensions
{
    public static JsonReader AssertTokenType(this JsonReader reader, JsonToken tokenType) => 
        reader.TokenType == tokenType ? reader : throw new JsonSerializationException(string.Format("Unexpected token {0}, expected {1}", reader.TokenType, tokenType));
    
    public static JsonReader ReadToContentAndAssert(this JsonReader reader) =>
        reader.ReadAndAssert().MoveToContentAndAssert();

    public static JsonReader MoveToContentAndAssert(this JsonReader reader)
    {
        if (reader == null)
            throw new ArgumentNullException();
        if (reader.TokenType == JsonToken.None)       // Skip past beginning of stream.
            reader.ReadAndAssert();
        while (reader.TokenType == JsonToken.Comment) // Skip past comments.
            reader.ReadAndAssert();
        return reader;
    }

    public static JsonReader ReadAndAssert(this JsonReader reader)
    {
        if (reader == null)
            throw new ArgumentNullException();
        if (!reader.Read())
            throw new JsonReaderException("Unexpected end of JSON stream.");
        return reader;
    }
}

然后,假设您的金融市场订单模型如下所示:

代码语言:javascript
复制
public class OrderBook
{
    public Order [] Orders { get; set; }
}

您可以按以下方式反序列化:

代码语言:javascript
复制
int maxLength = 20;  // Or whatever you want.
var settings = new JsonSerializerSettings
{
    Converters = { new MaxLengthArrayConverter<Order>(maxLength) },
};
var model = JsonConvert.DeserializeObject<OrderBook>(json, settings);

Assert.IsTrue(model.Orders.Length <= maxLength);

备注:

  • 在您的问题中,您只提到数组,但是如果您的模型实际上使用的是列表而不是数组,请使用以下转换器: 公共类MaxLengthListConverter : JsonConverter { public MaxLengthListConverter(int maxLength) => this.MaxLength = maxLength >= 0?(List)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();maxLength :抛出新的ArgumentException(nameof( MaxLength ));公共int MaxLength{ get;}公共覆盖列表ReadJson(JsonReader读取器,类型objectType,列表existingValue,bool hasExistingValue,JsonSerializer序列化程序){ if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)返回null;reader.AssertTokenType(JsonToken.StartArray);reader.AssertTokenType MaxLength();而(reader.ReadToContentAndAssert().TokenType != JsonToken.EndArray) { if (existingValue.Count < MaxLength) .TokenType else reader.Skip();}返回existingValue;}公共覆盖bool CanWrite => false;公共覆盖void WriteJson(JsonWriter编写器,列表值,JsonSerializer序列化程序) =>抛出新NotImplementedException();}
  • 这个答案假设您希望在运行时将模型中所有类型为T []的数组截断到特定长度。如果这不是真的,并且在运行时单独指定不同的数组需要不同的最大长度,那么您将需要一个更复杂的解决方案,可能涉及自定义契约解析器。

演示小提琴这里

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69524417

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档