Ellbar
Ellbar

Reputation: 4054

Odata - how to parse filters

I have Odata filter which is string and looks like that:

string odataFilter = "name eq 20 and surname eq 50"

What I need to accomplish is to get following dictionary from it:

dict["name"] = "20"
dict["surname"] = "50"

What is also important: I want to handle only "and" and "eq" keywords from odata. Nothing else.

Does anyone have an idea how to touch the problem? Maybe by regular expressions?

Upvotes: 0

Views: 1933

Answers (2)

Ellbar
Ellbar

Reputation: 4054

After few hours I created a regex which fits my needs very well. It accepts text values only as a string between apostrophes ('). In addition you can pass number value without them.

Example: name eq 'John' and age eq 75

Results in regex are grouped so it easily to get them from matches collection.

"(?<PropertyName>\w+?)\s+(?<Operator>eq)\s+(?<Value>(['])(\\?.)*?\1|\d+(\.\d+)?(\s*|$))(?:\s*$|\s+(?:and)(\s+|$))"

Upvotes: 1

Jimbot
Jimbot

Reputation: 716

I would use Regex.Split like this : https://dotnetfiddle.net/l1wueA

using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var dic = findAllAndEqFilter("name eq 20 and surname eq 50");

        Console.WriteLine("Test 1\r\n");
        foreach(var kpv in dic)
            Console.WriteLine(kpv.Key + "->" + kpv.Value);

        dic = findAllAndEqFilter("name eq 21 or surname eq 51");

        Console.WriteLine("\r\nTest 2\r\n");
        foreach(var kpv in dic)
            Console.WriteLine(kpv.Key + "->" + kpv.Value);

        dic = findAllAndEqFilter("name eq 22");

        Console.WriteLine("\r\nTest 3\r\n");
        foreach(var kpv in dic)
            Console.WriteLine(kpv.Key + "->" + kpv.Value);

        dic = findAllAndEqFilter("name lt 22");

        Console.WriteLine("\r\nTest 4\r\n");
        foreach(var kpv in dic)
            Console.WriteLine(kpv.Key + "->" + kpv.Value);
    }

    public static Dictionary<string, string> findAllAndEqFilter(string odataFilter)
    {
        Dictionary<string, string> ret = new Dictionary<string, string>(); 


        string[] byAnd = Regex.Split(odataFilter, "( and )");           

        string key = "";        

        foreach(var andSplit in byAnd)
            if(!Regex.IsMatch(andSplit, "( and )")) // remove the and       
            {
                string[] byEq = Regex.Split(andSplit, "( eq )");
                foreach(var eqSplit in byEq)
                    if(!Regex.IsMatch(eqSplit, "\\s")) // if there is no space, we can assume we got a eq       
                        if(key == "")
                            key = eqSplit;
                        else 
                        {
                            ret.Add(key, eqSplit);
                            key = "";
                        }

            }


        return ret;
    }
}

Upvotes: 2

Related Questions