コード例 #1
0
        ///<inheritdoc/>
        public override MultiFilter Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartObject)
            {
                throw new JsonException("Multifilter json must start with '{'.");
            }

            reader.Read();

            if (reader.TokenType != JsonTokenType.PropertyName || MultiFilter.LogicJsonPropertyName != reader.GetString())
            {
                throw new JsonException($@"Expected ""{MultiFilter.LogicJsonPropertyName}"" property.");
            }

            reader.Read();
            FilterLogic logic = reader.GetString()?.ToLowerInvariant() switch
            {
                "and" => FilterLogic.And,
                "or" => FilterLogic.Or,
                object value => throw new JsonException(@$ "Unexpected " "{value}" " value for " "{MultiFilter.LogicJsonPropertyName}" " property."),
                      null => throw new JsonException(@$ "Unexpected " "null" " value for " "{MultiFilter.LogicJsonPropertyName}" " property.")
            };

            IList <IFilter> filters = new List <IFilter>();

            if (reader.Read() && (reader.TokenType != JsonTokenType.PropertyName || MultiFilter.FiltersJsonPropertyName != reader.GetString()))
            {
                throw new JsonException($@"Expected ""{MultiFilter.FiltersJsonPropertyName}"" property.");
            }

            reader.Read();
            if (reader.TokenType != JsonTokenType.StartArray)
            {
                throw new JsonException(@"Expected ""["".");
            }

            reader.Read();

            // We are about to try parsing the JSON to get either a Filter or a MultiFilter.
            // We store a copy of the original reader in case the parsing process fails.
            Utf8JsonReader readerCopy = reader;

            while (reader.TokenType != JsonTokenType.EndArray)
            {
                long position = reader.TokenStartIndex;
                try
                {
                    filters.Add(_filterConverter.Read(ref reader, typeof(Filter), options));
                }
                catch
                {
                    // The json is not a Filter so we need to go back to where the parsing was performed
                    // and try to get a MultFilter instead

                    // 1. The copyReader position is moved to where the original parser were before failing
                    while (readerCopy.TokenStartIndex < position)
                    {
                        readerCopy.Read();
                    }

                    // 2. Try to parse the Json and get a MultiFilter.
                    filters.Add(Read(ref readerCopy, typeof(MultiFilter), options));
                    // The parsing was a success -> we move the reader to the continue the parsing process

                    while (reader.TokenStartIndex < readerCopy.TokenStartIndex)
                    {
                        reader.Read();
                    }
                    reader.Read(); // Advances the reader until the next token
                }
            }

            reader.Read();
            if (reader.TokenType != JsonTokenType.EndObject)
            {
                throw new JsonException(@"Expected ""}"".");
            }

            return(new MultiFilter
            {
                Logic = logic,
                Filters = filters
            });
        }