您可以创建以下JsonConverter<T []>,它将跳过超出特定计数的数组条目:
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;
}
}
然后,假设您的金融市场订单簿模型如下所示:
public class OrderBook
{
public Order [] Orders { get; set; }
}
可以如下反序列化:
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);
注意事项:
-
在您的问题中,您只提到了数组,但如果您的模型实际上使用的是列表而不是数组,请改用以下转换器:
public class MaxLengthListConverter<T> : JsonConverter<List<T>>
{
public MaxLengthListConverter(int maxLength) => this.MaxLength = maxLength >= 0 ? maxLength : throw new ArgumentException(nameof(maxLength));
public int MaxLength { get; }
public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
return null;
reader.AssertTokenType(JsonToken.StartArray);
existingValue ??= (List<T>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
existingValue.Clear();
while (reader.ReadToContentAndAssert().TokenType != JsonToken.EndArray)
{
if (existingValue.Count < MaxLength)
existingValue.Add(serializer.Deserialize<T>(reader));
else
reader.Skip();
}
return existingValue;
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer) => throw new NotImplementedException();
}
-
此答案假定您希望模型中的所有 T [] 类型的数组在运行时被截断为某个特定长度。如果这不是真的,并且您需要在运行时单独指定不同数组的不同最大长度,您将需要一个更复杂的解决方案,可能涉及自定义合约解析器。
演示小提琴here.