{"id":546,"date":"2020-09-06T00:57:00","date_gmt":"2020-09-05T11:57:00","guid":{"rendered":"https:\/\/blog.wiseowls.co.nz\/?p=546"},"modified":"2026-03-08T00:44:47","modified_gmt":"2026-03-07T11:44:47","slug":"parsing-odata-queries","status":"publish","type":"post","link":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/","title":{"rendered":"Parsing OData queries"},"content":{"rendered":"\n<p>OData (Open Data Protocol) is an&nbsp;ISO approved standard&nbsp;that defines a set of best practices for building and consuming RESTful APIs. It allows us write business logic and not worry too much about request and response headers, status codes, HTTP methods, and other variables.<\/p>\n\n\n\n<p>We won&#8217;t go into too much detail on how to write OData queries and how to use it &#8211; there&#8217;s <a href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/web-api\/overview\/odata-support-in-aspnet-web-api\/odata-v4\/create-an-odata-v4-endpoint\">plenty resources<\/a> out there. We&#8217;ll rather have a look at a bit esoteric scenario where we consider defining our own parser and then walking the&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Abstract_syntax_tree\">AST<\/a>&nbsp;to get desired values. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Problem statement<\/h2>\n\n\n\n<p>Suppose we&#8217;ve got a filter string that we received from the client:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">\"?$filter =((Name eq 'John' or Name eq 'Peter') and (Department eq 'Professional Services'))\"<\/code><\/pre>\n\n\n\n<p>And we&#8217;d like to apply custom validation to the filter. Ideally we&#8217;d like to get a structured list of properties and values so we can run our checks:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\">Filter 1:\n    Key: Name\n    Operator: eq\n    Value: John\nOperator: or\n\nFilter 2:\n    Key: Name\n    Operator: eq\n    Value: Peter\n\nOperator: and\n\nFilter 3:\n    Key: Department\n    Operator: eq\n    Value: Professional Services<\/code><\/pre>\n\n\n\n<p>Some options are:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/odata\/odatalib\/use-uri-parser\">ODataUriParser<\/a> &#8211; but it seems to have some issues with .net Core support just yet<\/li><li>Regular Expression&nbsp;&#8211; not very flexible<\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/microsoft.aspnet.odata.query.odataqueryoptions?view=odata-aspnetcore-7.0\">ODataQueryOptions<\/a>&nbsp;&#8211; produces <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/microsoft.aspnet.odata.query.odataqueryoptions.rawvalues?view=odata-aspnetcore-7.0#Microsoft_AspNet_OData_Query_ODataQueryOptions_RawValues\">raw<\/a> text but cannot broken down any further<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What else?<\/h2>\n\n\n\n<p>One other way to approach this would be parsing. And there are plenty tools to do that (see&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Flex_(lexical_analyser_generator)\">flex<\/a>&nbsp;or&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/GNU_Bison\">bison<\/a>&nbsp;for example). In .net world, however, <a href=\"https:\/\/github.com\/IronyProject\/Irony\">Irony<\/a>&nbsp;might be a viable option: it&#8217;s available in&nbsp;<code>.net standard 2.0<\/code>&nbsp;which we had no issues plugging into a&nbsp;<code>.net core 3.1<\/code>&nbsp;console test project.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Grammar<\/h2>\n\n\n\n<p>To start off, we normally need to define a grammar. But luckily, Microsoft have been kind enough to&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/search\/search-query-odata-syntax-reference\">supply us with EBNF reference<\/a>&nbsp;so all we have to do is to adapt it to Irony. I ended up implementing a subset of the grammar above that seems to cater for example statement (and a bit above and beyond, feel free to cut it down).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">using Irony.Parsing;\n\nnamespace irony_playground\n{\n    [Language(\"OData\", \"1.0\", \"OData Filter\")]\n    public class OData: Grammar\n    {\n        public OData()\n        {\n            \/\/ first we define some terms\n            var identifier = new RegexBasedTerminal(\"identifier\", \"[a-zA-Z_][a-zA-Z_0-9]*\");\n            var string_literal = new StringLiteral(\"string_literal\", \"'\");\n            var integer_literal = new NumberLiteral(\"integer_literal\", NumberOptions.IntOnly);\n            var float_literal = new NumberLiteral(\"float_literal\", NumberOptions.AllowSign|NumberOptions.AllowSign) \n                                        | new RegexBasedTerminal(\"float_literal\", \"(NaN)|-?(INF)\");\n            var boolean_literal = new RegexBasedTerminal(\"boolean_literal\", \"(true)|(false)\");\n\n            var filter_expression = new NonTerminal(\"filter_expression\");\n            var boolean_expression = new NonTerminal(\"boolean_expression\");\n            var collection_filter_expression = new NonTerminal(\"collection_filter_expression\");\n            var logical_expression = new NonTerminal(\"logical_expression\");\n            var comparison_expression = new NonTerminal(\"comparison_expression\");\n            var variable = new NonTerminal(\"variable\");\n            var field_path = new NonTerminal(\"field_path\");\n            var lambda_expression = new NonTerminal(\"lambda_expression\");\n            var comparison_operator = new NonTerminal(\"comparison_operator\");\n            var constant = new NonTerminal(\"constant\");\n\n            Root = filter_expression; \/\/ this is where our entry point will be. \n\n            \/\/ and from here on we expand on all terms and their relationships\n            filter_expression.Rule = boolean_expression;\n\n            boolean_expression.Rule = collection_filter_expression\n                                      | logical_expression\n                                      | comparison_expression\n                                      | boolean_literal\n                                      | \"(\" + boolean_expression + \")\"\n                                      | variable;\n            variable.Rule = identifier | field_path;\n\n            field_path.Rule = MakeStarRule(field_path, ToTerm(\"\/\"), identifier);\n\n            collection_filter_expression.Rule =\n                field_path + \"\/all(\" + lambda_expression + \")\"\n                | field_path + \"\/any(\" + lambda_expression + \")\"\n                | field_path + \"\/any()\";\n\n            lambda_expression.Rule = identifier + \":\" + boolean_expression;\n\n            logical_expression.Rule =\n                boolean_expression + (ToTerm(\"and\", \"and\") | ToTerm(\"or\", \"or\")) + boolean_expression\n                | ToTerm(\"not\", \"not\") + boolean_expression;\n\n            comparison_expression.Rule =\n                variable + comparison_operator + constant |\n                constant + comparison_operator + variable;\n\n            constant.Rule =\n                string_literal\n                | integer_literal\n                | float_literal\n                | boolean_literal\n                | ToTerm(\"null\");\n\n            comparison_operator.Rule = ToTerm(\"gt\") | \"lt\" | \"ge\" | \"le\" | \"eq\" | \"ne\";\n\n            RegisterBracePair(\"(\", \")\");\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>NB: Irony comes with Grammar Explorer tool that allows us to load grammar dlls and debug them with free text input.<\/p><\/blockquote>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/i.stack.imgur.com\/caUtE.png\"><img decoding=\"async\" src=\"https:\/\/i.stack.imgur.com\/caUtE.png\" alt=\"enter image description here\"\/><\/a><\/figure>\n\n\n\n<p>after we&#8217;re happy with the grammar, we need to reference it from our project and parse the input string:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">class Program\n{\n    static void Main(string[] args)\n    {\n        var g = new OData();\n        var l = new LanguageData(g);\n        var r = new Parser(l);\n        var p = r.Parse(\"((Name eq 'John' or Name eq 'Grace Paul') and (Department eq 'Finance and Accounting'))\"); \/\/ here's your tree\n        \/\/ this is where you walk it and extract whatever data you desire \n    }\n}<\/code><\/pre>\n\n\n\n<p>Then, all we&#8217;ve got to do is walk the resulting tree and apply any custom logic based on syntax node type. One example how to do that can be found in&nbsp;<a href=\"https:\/\/stackoverflow.com\/questions\/15012865\/how-do-i-work-with-the-ast-in-irony-now\">this StackOverflow answer<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>OData (Open Data Protocol) is an&nbsp;ISO approved standard&nbsp;that defines a set of best practices for building and consuming RESTful APIs. It allows us write business logic and not worry too much about request and response headers, status codes, HTTP methods, and other variables. We won&#8217;t go into too much detail on how to write OData &hellip; <a href=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Parsing OData queries&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":381,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[11],"tags":[12],"class_list":["post-546","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","tag-c"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Parsing OData queries - Timur and associates<\/title>\n<meta name=\"description\" content=\"Parsing OData filter expressions by walking the AST. Useful when you need custom validation beyond what the framework provides.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Parsing OData queries - Timur and associates\" \/>\n<meta property=\"og:description\" content=\"Parsing OData filter expressions by walking the AST. Useful when you need custom validation beyond what the framework provides.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/\" \/>\n<meta property=\"og:site_name\" content=\"Timur and associates\" \/>\n<meta property=\"article:published_time\" content=\"2020-09-05T11:57:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-07T11:44:47+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1282\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"timur\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@TimurKh\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/\"},\"author\":{\"name\":\"timur\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\"},\"headline\":\"Parsing OData queries\",\"datePublished\":\"2020-09-05T11:57:00+00:00\",\"dateModified\":\"2026-03-07T11:44:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/\"},\"wordCount\":381,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg\",\"keywords\":[\"c#\"],\"articleSection\":[\"Development\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/\",\"url\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/\",\"name\":\"Parsing OData queries - Timur and associates\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg\",\"datePublished\":\"2020-09-05T11:57:00+00:00\",\"dateModified\":\"2026-03-07T11:44:47+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\"},\"description\":\"Parsing OData filter expressions by walking the AST. Useful when you need custom validation beyond what the framework provides.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg\",\"contentUrl\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg\",\"width\":1920,\"height\":1282,\"caption\":\"Photo by Ilya Pavlov on Unsplash\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/09\\\/06\\\/parsing-odata-queries\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Parsing OData queries\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#website\",\"url\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/\",\"name\":\"Timur and associates\",\"description\":\"Notes of an IT contractor\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\",\"name\":\"timur\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"caption\":\"timur\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/TimurKh\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Parsing OData queries - Timur and associates","description":"Parsing OData filter expressions by walking the AST. Useful when you need custom validation beyond what the framework provides.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/","og_locale":"en_US","og_type":"article","og_title":"Parsing OData queries - Timur and associates","og_description":"Parsing OData filter expressions by walking the AST. Useful when you need custom validation beyond what the framework provides.","og_url":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/","og_site_name":"Timur and associates","article_published_time":"2020-09-05T11:57:00+00:00","article_modified_time":"2026-03-07T11:44:47+00:00","og_image":[{"width":1920,"height":1282,"url":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg","type":"image\/jpeg"}],"author":"timur","twitter_card":"summary_large_image","twitter_creator":"@TimurKh","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/#article","isPartOf":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/"},"author":{"name":"timur","@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59"},"headline":"Parsing OData queries","datePublished":"2020-09-05T11:57:00+00:00","dateModified":"2026-03-07T11:44:47+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/"},"wordCount":381,"commentCount":0,"image":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg","keywords":["c#"],"articleSection":["Development"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/","url":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/","name":"Parsing OData queries - Timur and associates","isPartOf":{"@id":"https:\/\/blog.wiseowls.co.nz\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/#primaryimage"},"image":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg","datePublished":"2020-09-05T11:57:00+00:00","dateModified":"2026-03-07T11:44:47+00:00","author":{"@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59"},"description":"Parsing OData filter expressions by walking the AST. Useful when you need custom validation beyond what the framework provides.","breadcrumb":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/#primaryimage","url":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg","contentUrl":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/ilya-pavlov-OqtafYT5kTw-unsplash-scaled-e1581852574473.jpg","width":1920,"height":1282,"caption":"Photo by Ilya Pavlov on Unsplash"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/09\/06\/parsing-odata-queries\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.wiseowls.co.nz\/"},{"@type":"ListItem","position":2,"name":"Parsing OData queries"}]},{"@type":"WebSite","@id":"https:\/\/blog.wiseowls.co.nz\/#website","url":"https:\/\/blog.wiseowls.co.nz\/","name":"Timur and associates","description":"Notes of an IT contractor","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.wiseowls.co.nz\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59","name":"timur","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","caption":"timur"},"sameAs":["https:\/\/x.com\/TimurKh"]}]}},"_links":{"self":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/546","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/comments?post=546"}],"version-history":[{"count":12,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/546\/revisions"}],"predecessor-version":[{"id":1232,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/546\/revisions\/1232"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/media\/381"}],"wp:attachment":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/media?parent=546"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/categories?post=546"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/tags?post=546"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}