Giter VIP home page Giter VIP logo

jmespath.site's Introduction

JMESPath

JMESPath (pronounced "james path") allows you to declaratively specify how to extract elements from a JSON document.

For example, given this document:

{"foo": {"bar": "baz"}}

The jmespath expression foo.bar will return "baz".

JMESPath also supports:

Referencing elements in a list. Given the data:

{"foo": {"bar": ["one", "two"]}}

The expression: foo.bar[0] will return "one". You can also reference all the items in a list using the * syntax:

{"foo": {"bar": [{"name": "one"}, {"name": "two"}]}}

The expression: foo.bar[*].name will return ["one", "two"]. Negative indexing is also supported (-1 refers to the last element in the list). Given the data above, the expression foo.bar[-1].name will return "two".

The * can also be used for hash types:

{"foo": {"bar": {"name": "one"}, "baz": {"name": "two"}}}

The expression: foo.*.name will return ["one", "two"].

Installation

You can install JMESPath from pypi with:

pip install jmespath

API

The jmespath.py library has two functions that operate on python data structures. You can use search and give it the jmespath expression and the data:

>>> import jmespath
>>> path = jmespath.search('foo.bar', {'foo': {'bar': 'baz'}})
'baz'

Similar to the re module, you can use the compile function to compile the JMESPath expression and use this parsed expression to perform repeated searches:

>>> import jmespath
>>> expression = jmespath.compile('foo.bar')
>>> expression.search({'foo': {'bar': 'baz'}})
'baz'
>>> expression.search({'foo': {'bar': 'other'}})
'other'

This is useful if you're going to use the same jmespath expression to search multiple documents. This avoids having to reparse the JMESPath expression each time you search a new document.

Options

You can provide an instance of jmespath.Options to control how a JMESPath expression is evaluated. The most common scenario for using an Options instance is if you want to have ordered output of your dict keys. To do this you can use either of these options:

>>> import jmespath
>>> jmespath.search('{a: a, b: b}',
...                 mydata,
...                 jmespath.Options(dict_cls=collections.OrderedDict))


>>> import jmespath
>>> parsed = jmespath.compile('{a: a, b: b}')
>>> parsed.search(mydata,
...               jmespath.Options(dict_cls=collections.OrderedDict))

Custom Functions

The JMESPath language has numerous built-in functions, but it is also possible to add your own custom functions. Keep in mind that custom function support in jmespath.py is experimental and the API may change based on feedback.

If you have a custom function that you've found useful, consider submitting it to jmespath.site and propose that it be added to the JMESPath language. You can submit proposals here.

To create custom functions:

  • Create a subclass of jmespath.functions.Functions.
  • Create a method with the name _func_<your function name>.
  • Apply the jmespath.functions.signature decorator that indicates the expected types of the function arguments.
  • Provide an instance of your subclass in a jmespath.Options object.

Below are a few examples:

import jmespath
from jmespath import functions

# 1. Create a subclass of functions.Functions.
#    The function.Functions base class has logic
#    that introspects all of its methods and automatically
#    registers your custom functions in its function table.
class CustomFunctions(functions.Functions):

    # 2 and 3.  Create a function that starts with _func_
    # and decorate it with @signature which indicates its
    # expected types.
    # In this example, we're creating a jmespath function
    # called "unique_letters" that accepts a single argument
    # with an expected type "string".
    @functions.signature({'types': ['string']})
    def _func_unique_letters(self, s):
        # Given a string s, return a sorted
        # string of unique letters: 'ccbbadd' ->  'abcd'
        return ''.join(sorted(set(s)))

    # Here's another example.  This is creating
    # a jmespath function called "my_add" that expects
    # two arguments, both of which should be of type number.
    @functions.signature({'types': ['number']}, {'types': ['number']})
    def _func_my_add(self, x, y):
        return x + y

# 4. Provide an instance of your subclass in a Options object.
options = jmespath.Options(custom_functions=CustomFunctions())

# Provide this value to jmespath.search:
# This will print 3
print(
    jmespath.search(
        'my_add(`1`, `2`)', {}, options=options)
)

# This will print "abcd"
print(
    jmespath.search(
        'foo.bar | unique_letters(@)',
        {'foo': {'bar': 'ccbbadd'}},
        options=options)
)

Again, if you come up with useful functions that you think make sense in the JMESPath language (and make sense to implement in all JMESPath libraries, not just python), please let us know at jmespath.site.

Specification

If you'd like to learn more about the JMESPath language, you can check out the JMESPath tutorial. Also check out the JMESPath examples page for examples of more complex jmespath queries.

The grammar is specified using ABNF, as described in RFC4234. You can find the most up to date grammar for JMESPath here.

You can read the full JMESPath specification here.

Testing

In addition to the unit tests for the jmespath modules, there is a tests/compliance directory that contains .json files with test cases. This allows other implementations to verify they are producing the correct output. Each json file is grouped by feature.

Discuss

Join us on our Gitter channel if you want to chat or if you have any questions.

jmespath.site's People

Contributors

brlin-tw avatar chadselph avatar dreftymac avatar gpacix avatar iconara avatar jamesls avatar liancheng avatar mbrightcpacket avatar mdavis-xyz avatar mtdowling avatar olivergondza avatar pmarkert avatar richardbronosky avatar robertmrk avatar sebastien-rosset avatar springcomp avatar teppeis avatar trevorrowe avatar vladik-vitre avatar waisbrot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

jmespath.site's Issues

More examples on selecting nested data

Hello, it'd be appreciated if you could provide guidance on this one. I'd like to obtain the "general" object for the ID == 100.Thanks a lot in advance!

{
  "people": [
    {
      "general": {
        "id": "100",
        "age": 20,
        "other": "foo",
        "name": "Bob"
      },
      "history": {
        "first_login": "2014-01-01",
        "last_login": "2014-01-02"
      }
    },
    {
      "general": {
        "id": "101",
        "age": 30,
        "other": "bar",
        "name": "Bill"
      },
      "history": {
        "first_login": "2014-05-01",
        "last_login": "2014-05-02"
      }
    }
  ]
}

Please help me decide about extending syntax for jmespath

I am in process of starting new project extending jmespath with more syntax. Currently now I work on basic jmespath and extend it to support math operation + - * / % with antlr. I got the antlr file from https://github.com/burtcorp/jmespath-java

I am now stuck on design decision and wish that you could kindly help me with some suggestion

  • Should I support bitwise operation with && || ^ ?

    • Is it acceptable to use && and || as bitwise operator?
      • 1 || 2 will return 3 for instance
    • And still wonder is it really necessary, especially xor operator ^
      • But if I include this ^ operator, it also support boolean xor in addition to && and ||
  • Should I bring back root node $ from jsonpath?

  • Should I bring back ** operator from jsonpath?

  • Should I support ternary condition ? true : false operator ?

  • Should I support ?? and ?! operator ?

    • And remove support on && || for null check in the same manner of js
      • It might be used as bitwise operator above instead
    • One difference is it will not treat false as null. Only null and empty
  • I would like to add support to backtracing to parent node with @.. syntax

    • nth number of dots - 1 will backtrack to nth parent
      • $.me.obj.. is equal to $.me
      • $.me.obj... is equal to $
    • Is there any better syntax for this ?
  • I would like to add support to index value with # symbol

    • For array, # would be index number 0,1,2,...
    • For object, # would be string "{key}"
    • What should I do for deep reference ?
      • # for current level, ## for previous level ?
        • $.me.obj[0].# return 0
        • $.me.obj[0].## return "obj"
        • $.me.obj[0].### return "me"
      • # for current level, ..# for previous level ?
        • $.me.obj[0].# return 0
        • $.me.obj[0]..# return "obj"
        • $.me.obj[0]...# return "me"
      • # for current level, ## will be fullpath as array?
        • $.me.obj[0].# return 0
        • $.me.obj[0].## return ["me","obj",0]
    • What should I do for slice and query? # will be index of sliced iteration or actual index?
  • I would like to support object projection key by expression #64

  • Any other idea overall? Any other things you don't satisfied with jmespath?

is it possible to access parent node?

Hello, I'd like to filter and get as result the parent. Is it possible?

For example, here I'd like to filter by "my.name" and get as result the "created : T1" field

Regards
Enric


      "histories":[
         {
            "id":"556248",
            "author":{
               "name":"my.name",
            },
            "created":"T1"
	  },
         {
            "id":"556249",
            "author":{
               "name":"other.name",
            },
            "created":"T2"
	  }
       ]

Example on filtering nested non-list objects

There are a lot of examples on how to filter lists, but that doesn't seem to work on non-list objects.
Example:

{"a": 1, "b": {"c" : 100}}

If I want to filter by c == 100 this will not work b[?c==100]. What should be used instead? Also how to filter by a == 1?

website try-out fails to conform to it's own spec

Pasting the following query into the box

locations[?state > 'N'].name | sort(@) | {WashingtonCities: join(', ', @)}

returns:

{
  "WashingtonCities": "Bellevue, Olympia, Seattle"
}

whereas of course according to spec (and indeed the official jp utility) the answer should be:

{
  "WashingtonCities": ""
}

Now in an ideal world, you'd bump and fix the spec and the currently "correct" implementations, because not having the ability to compare strings makes common and trivially written filtering operations like [?start_date > '2018-01-01'] essentially impossible. Which is particularly galling given that you already have opened the pandora's box of unicode string comparisons by allow max over strings (of course without giving any explanation of what the actual behaviour is -- are you comparing UTF-16 codepoints like javascript? UTF-8 bytes? UTF-32 codepoints?...).

In a less ideal world, you'd fix the spec by actually saying what max does on strings (or disallowing it) and making your try box conform to it.

how to query that a hash contains a key?

I can't find anything that illuminates my problem.

Given data:

   {
        "Origin": "CreateRoute",
        "DestinationCidrBlock": "10.12.160.0/20",
        "State": "active",
        "VpcPeeringConnectionId": "pcx-851234ed"
    },
    {
        "Origin": "CreateRoute",
        "DestinationCidrBlock": "10.13.176.0/20",
        "State": "active",
        "VpcPeeringConnectionId": "pcx-bdffffd5"
    },
    {
        "GatewayId": "vgw-0a12ab63",
        "DestinationCidrBlock": "10.0.0.0/8",
        "State": "active",
        "Origin": "CreateRoute"
    },
    {
        "Origin": "CreateRoute",
        "DestinationCidrBlock": "0.0.0.0/0",
        "NatGatewayId": "nat-0e902b64123458915",
        "State": "active"
    },

how do I query to pick only the hashes that contain the key 'VpcPeeringConnectionId'?

Multiple conditions and nested data

Hi. I would like to get help with this query.

if company_info.active = TRUE and company_info.company_employees.salary > 4200

The response im searching for is this:

[
  {
    "company_id": 3,
    "company_info": {
      "active": true,
      "company_employees": [
        {
          "id": "1",
          "name": "Charlotte Doe",
          "salary": "4500"
        },
        {
          "id": "2",
          "name": "Chris Doe",
          "salary": "5200"
        }
      ]
    }
  }
]

Here is example from the full object.

[
  {
    "company_id": 1,
    "company_info": {
      "active": true,
      "company_employees": [
        {
          "id": "1",
          "name": "John Doe",
          "salary": "2500"
        },
        {
          "id": "2",
          "name": "Liza Doe",
          "salary": "3200"
        }
      ]
    }
  },
  {
    "company_id": 2,
    "company_info": {
      "active": false,
      "company_employees": [
        {
          "id": "1",
          "name": "Jacob Doe",
          "salary": "6500"
        },
        {
          "id": "2",
          "name": "Hanna Doe",
          "salary": "8200"
        }
      ]
    }
  },
  {
    "company_id": 3,
    "company_info": {
      "active": true,
      "company_employees": [
        {
          "id": "1",
          "name": "Charlotte Doe",
          "salary": "4500"
        },
        {
          "id": "2",
          "name": "Chris Doe",
          "salary": "5200"
        }
      ]
    }
  }
]

More examples on Concatenating nested elements

Hi,

I think it would be very nice to add an example on how to use a join to concatenate the values of two keys inside a nested list of key values.

Using the query syntax I tried to create tuples combining the values of name and value(see below json structure) but it took me a lot of time to figure that out as there was no specific example on the Jmespath official web doc (the online jmspath validators didn't help neither in my case) .

Anyway, in order to get that I had to run the below

 [*].capabilities[].join(':',[name,value])

below is the json source input

[
  {
    "apiVersions": null,
    "capabilities": [
      {
        "name": "MaxResourceVolumeMB",
        "value": "10240"
      },
      {
        "name": "OSVhdSizeMB",
        "value": "1047552"
      },
      {
        "name": "vCPUs",
        "value": "1"
      },
      {
        "name": "HyperVGenerations",
        "value": "V1"
      },
      {
        "name": "MemoryGB",
        "value": "2"
      },
      {
        "name": "MaxNetworkInterfaces",
        "value": "2"
      }
    ],
    "capacity": null,
    "costs": null,
    "family": "standardAv2Family",
    "kind": null,
    "locationInfo": [
      {
        "location": "eastus",
        "zoneDetails": [],
        "zones": [
          "3",
          "2",
          "1"
        ]
      }
    ],
    "locations": [
      "eastus"
    ],
    "name": "Standard_A1_v2",
    "resourceType": "virtualMachines",
    "restrictions": [],
    "size": "A1_v2",
    "tier": "Standard"
  },
..
}
]

the result will look like below :

[                                                             
  "MaxResourceVolumeMB:10240",                                
  "OSVhdSizeMB:1047552",                                      
  "vCPUs:1",                                                  
  "HyperVGenerations:V1",                                     
  "MemoryGB:2",                                                                                
  "MaxNetworkInterfaces:2"                                    
]                                                             

thanks

Support ES6-style compact object literals for multiselect

Say I have this JSON object and want to pare it down to just the ids and first names:

{
  "values": [
    {"id": 1, "first": "Bill", "last": "Gates"},
    {"id": 2, "first": "Larry", "last": "Page"}
  ]
}

I can do that with this expression: values[*].{id:id, first:first}.

Since {x:x, y:y} is such a common pattern, ES6 introduced compact object literal notation to simplify this. In ES6, {x,y} is equivalent to {x:x, y:y}.

I don't believe {x,y} is valid in JMESPath, so it would be a boon (and intuitive to JS users) to add this to the spec.

Add definition of JMESPath acronym

Add definition of JMESPath acronym, maybe in an About section

I guess the Acronym is something like this

Letter Meaning
J Javascript
M ???
E ???
S ???
Path Path

Show error in interactive examples when query is invalid

The interactive examples on the website are great!

I noticed though that when you're changing the JMESPath query and it becomes invalid, nothing happens. Would be great if the output would display an error instead of showing the last result.

I can create a PR for this I think if someone can point me to the code of these interactive examples.

How to query by key?

Hi I could not find the answer to this problem:

Given the following structure, how do I get all the "objects" those keys start with e.g 'block8'?

{
    "prod_data": {
        "block2.row2": {
            "status": "yes",
            "date": "2016-05-09",
            "name": "Karin",
            "time": "06:57:28"
        },
        "block8.row4": {
            "status": "yes",
            "date": "2016-05-18",
            "name": "Isolde",
            "time": "11:22:02"
        },
        "block3.row1": {
            "status": "yes",
            "date": "2016-05-13",
            "name": "Isolde",
            "time": "13:11:59"
        },
        "block8.row2": {
            "status": "yes",
            "date": "2016-05-18",
            "name": "Isolde",
            "time": "11:22:02"
        }
    }
}

Sum_by function

Hi!

it would be really nice to have sum_by function. My case is to get something like

[
  {
    "pool_name": "default",
    "num": 2
  },
  {
    "pool_name": "test",
    "num": 77
  },
  {
    "pool_name": "default",
    "num": 4
  }
]

sum services count in specific pool.
Several times as i can see it was already requested but in wrong projects. Here is request in i hope right one

Add a map() function

Not sure this warrants a full JEP, but I think it would be useful to have a map() function that takes two args, an expref and input data, and applies the expression ever every element in the second arg:

Signature:

array[any] map(expression->any->any, array[any])

Example:

map(&foo, `[{"foo": "a"}, {"foo": "b"}, {"foo": "c"}]`) -> ["a", "b", "c"]

At first, this might seem the exact same as a projection, so the example above could just be [*].foo.

However, there's a key difference: you will always know the size of the output array. That is, given an array of length N, map will always return back an array of length N. Projections will not include any element in the final list whose value is null. So really [*].bar is saying "for each element in the list, if there's a bar value, and it's not null, include it in the returned list.

The above feature (that is always producing an output of length N elements) has been requested several times before, most recently here.

The second is the ability to be more explicit with regard to what expression is being evaluated against each element. map() clearly takes two arguments, the first is the expression, the second is the input array. Sometimes, it's not possible to override the parser's precedence, for example the expression [*][], where conceptually you wan to say "try to flatten each element in the input array" is not possible because flatten has such a weak binding, the parser interprets Identity() for the RHS of the expression [*][]. This is discussed here: jmespath/jmespath.py#92. This would be much more explicit by just saying map(&[], myinput).

EDIT: More examples:

# Notice how there's a `None` value in the 3rd and 4th element
>>> jmespath.search('map(&foo, array)', {'array': [{'foo': 'a'}, {'foo': 'b'}, {}, [], {'foo': 'f'}]})
['a', 'b', None, None, 'f']

# What was requested in jmespath/jmespath.py#92:
>>> search('map(&[], @)', [[1, 2, 3, [4]], [5, 6, 7, [8, 9]]])
[[1, 2, 3, 4], [5, 6, 7, 8, 9]]

# From stackoverflow (http://stackoverflow.com/questions/32612193/jmespath-nested-or-statement):
>>> stackoverflow = [
...     {
...         'foo': {'bar': 'yes1'}
...     },
...     {
...         'foo': {'bar': 'yes2'}
...     },
...     {
...         'foo1': {'bar': 'no'}
...     }
... ]
>>> search('map(&foo.bar, [*])', stackoverflow)
['yes1', 'yes2', None]

Use HTTPS for site

Please use https for the website. It's embarrassing to use http these days. Obviously you can get a free cert from https://letsencrypt.org/ .

Also, the repo hasn't been updated in over a year even though there are so many Issues and PRs. If it's dead, please admit it and say so.

How to return a child node and a parent node attribute in the same query JMES Path for JSON object

Considert we have this JSON:

{  
   "A":[  
      {  
         "AT":"text"
      },
      {  
         "AT":"text2"
      }
   ],
   "B":[  
      {  
         "name":"text",
         "power":10
      },
      {  
         "name":"text1",
         "power":20
      },
      {  
         "name":"text2",
         "power":40
      }
   ]
}

I want to return "AT" and the power corresponding to "AT", so I don't want to return "text1" but just [["text",10],["text2",40]]. This query [A[*].AT,B[*].power] return this: [["text","text2"],[10,20,40]]. So it's not exactly what I want because I don't want the extra value: 20 from "text1". I found this portion of code root[*].B[?contains(['text','text2'],name)].[name,power][][] it return ["text",10,"text2",40] this is the good result BUT the query isn't dynamics, because in the contain I have this ['text','text2'] and I want to replace this portion of code with a nested query if it's possible, so, how can I do that ?
How can I fix that ?

Permalinks to an ID break javascript code

For example this breaks: http://jmespath.org/examples.html#working-with-nested-data
but this doesn't: http://jmespath.org/examples.html

The error appears to be from:

  fixFirefoxAnchorBug : function() {
    if (document.location.hash && $.browser.mozilla)
      window.setTimeout(function() {
        document.location.href += '';
      }, 10);
  },
Uncaught TypeError: Cannot read property 'mozilla' of undefined

Appears to stem from incompatible jquery versions: https://bitbucket.org/birkenfeld/sphinx/issue/1140

Selecting data from anonymous dictionary

I have an anonymous dictionary that looks like this:

{
        "fe-0/0/0": {
            "description": "Standard User Access",
            "is_enabled": true,
            "is_up": true,
            "last_flapped": 2257531.0,
            "mac_address": "40:A6:77:2B:FC:00",
            "speed": 100
        },
        "fe-0/0/1": {
            "description": "Standard User Access",
            "is_enabled": false,
            "is_up": true,
            "last_flapped": 428719.0,
            "mac_address": "40:A6:77:2B:FC:01",
            "speed": 100
        }
}

I've tried a number of combinations to select only the sub-dictionaries that have "is_enabled==true" but with no luck. I actually don't even need the high-level key name, the content of the dictionary would be sufficient.

Missing expression types in expression definition

The grammar does not include and-expression, not-expression or paren-expression under the definition of expression. Since there is no mention of these elsewhere in the specification, I suspect that they should indeed be considered expressions. In other words, I'm missing a line in the grammar equivalent to the following:

expression        =/ and-expression / not-expression / paren-expression

Alternatively, I would expect the specification to mention how and where these expression types are valid. It may also be the case that I have misunderstood something fundamentally or am completely blind.

Need examples on filtering non-object roots.

if my JSON starts out as an array:

[
    {
        "id": 1,
        "name": "one"
    },
    {
        "id": 2,
        "name": "two"
    },
    {
        "id": 3,
        "name": "three"
    }
]

I'm not sure how to begin my query so that I can do things like select where id > 1, etc...

example correction: count(@) is not there anymore

From examples on jmespath.org:

current-node¶
The current-node token can be used to represent the current node being evaluated. The current-node token is useful for functions that require the current node being evaluated as an argument. For example, the following expression creates an array containing the total number of elements in the foo object followed by the value of foo["bar"].

foo[].[count(@), bar

$ jp.py -f vminfo.json "virtual_machines.count(@)"
unknown-function: Unknown function: count()

Flatten projections with data fields from parent object containing the list

{
  "reservations": [
    {
      "instances": [
        {"type": "small",
         "state": {"name": "running"},
         "tags": [{"Key": "Name",
                   "Values": ["Web"]},
                  {"Key": "version",
                   "Values": ["1"]}]},
        {"type": "large",
         "state": {"name": "stopped"},
         "tags": [{"Key": "Name",
                   "Values": ["Web"]},
                  {"Key": "version",
                   "Values": ["1"]}]}
      ]
    }, {
      "instances": [
        {"type": "medium",
         "state": {"name": "terminated"},
         "tags": [{"Key": "Name",
                   "Values": ["Web"]},
                  {"Key": "version",
                   "Values": ["1"]}]},
        {"type": "xlarge",
         "state": {"name": "running"},
         "tags": [{"Key": "Name",
                   "Values": ["DB"]},
                  {"Key": "version",
                   "Values": ["1"]}]}
      ]
    }
  ]
}

I wish to select all tags as a flat list from above data:

reservations[].instances[].tags[]

However, I wish to select the "state" information of each instance as a key inside each tag object too. Could you please tell me how to achieve this.

max_by specification refers undefined people array

The description of max_by function says this:

Below are several examples using the people array (defined above) as the given input.

However, there's no definition of the people array at least on the specification page.

Filter hash keys in multiselect

Is there a way to remove a single key from a hash, rather than specifying a list of keys to keep?

For example, say I have a GeoJSON FeatureCollection and would like to remove all the geometry objects:

{
  "type": "FeatureCollection",
  "features": [
    {
      "id": "X",
      "type": "Feature",
      "properties": {
        "name": "Middle of nowhere"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -102.3046875,
          38.272688535980976
        ]
      }
    }
  ]
}

I can do that with features[*].{id:id,type:type,properties:properties}, but this would also filter out any unexpected keys in the feature.

It would be nice if there were a way to invert a multiselect, e.g. to specifically remove a key from a hash. Maybe something like features[*].{-geometry}.

How to transform Elasticsearch mutiple aggregation TopN

in Elasticsearch I have to query with mutiple aggregation, result like this:

[
    {
        "field_name1": "field_name1_value1",
        "field_name2": "field_name2_value1",
        "count": 2
        "topN": [{"name": "aaa"},{"name": "bbb"}]
    },
    {
        "field_name1": "field_name1_value2",
        "field_name2": "field_name2_value2",
        "count": 2
        "topN": [{"name": "ccc"},{"name": "ddd"}]
    },
    {
        "field_name1": "field_name1_value1",
        "field_name2": "field_name2_value2",
        "count": 3
        "topN": [{"name": "eee"},{"name": "fff"},{"name": "ggg"}]
    }
]

I hope transform it like this :

{
	"field_name1_value1": {
		"field_name2_value1": {
			"count": 2,
			"topN": [{"name": "aaa"},{"name": "bbb"}]
		},
		"field_name2_value2": {
			"count": 3,
			"topN": [{"name": "eee"},{"name": "fff"},{"name": "ggg"}]
		}
	},
	"field_name1_value2": {
		"field_name2_value2": {
			"count": 2,
			"topN": [{"name": "ccc"},{"name": "ddd"}]
		}
	}
}

how could I do

Is space supported in key?

If I use

[?a.b c==`value`].a

it will report an error.
May I know how to select "b c"? Look forward to your answer.

max_by/min_by specification disagrees with the examples

The max_by and min_by specification declares that the 2nd argument is an expression that returns either a number or a string.

expression->number|expression->string

However, they both have an example that specifically contradicts this showing that strings are not allowed. Which is it?

Expression Result
max_by(people, &age_str) <error: invalid-type>
min_by(people, &age_str) error: invalid-type

Custom functions

The function expression grammar and built-in functions give me the impression that custom function is supported. However, there is no docs on how to create a custom function. Does it vary by language-specific library? Please clarify. I use jmespath.js.

This feature is important to me because built-in functions seem lacking some basic features, for example case sensitivity option for string matching functions such as contains.

filter on key containing special character

Data Structure

{
  "objects": [
    {
      "@TYPE": A,
      "$": "one",
    },
    {
      "@TYPE": B,
      "$": "two",
    },
    {
      "@TYPE": C,
      "$": "three",
    }
  ]
}

Question

I am trying to write a query that will return "one". I have tried the following:
objects[?@TYPE == "A"]."$" this is a syntax error
objects[?"@TYPE" == "A"]."$" this returns an empty array
objects[?"\@TYPE" == "A"]."$" this is a syntax error
objects[?"/@TYPE" == "A"]."$" this returns ["one", "two", "three"] which is a surprise...

What is the proper way to escape the @ in the key name?

JSON Transformation fails when expression has static string and JSON Path formatted more than a single line

Hi,

My Data is
{
"title": "title1",
"description": "description1",
"blog": "This is a blog.",
"date": "11/4/2013"
}
My Expression is
{
"data":{
"date":date,
"text":blog
},
"name":title,
"description":description
}

It is not working since the expression is formatted and has \r\n.

If I give expression as single line minified, It works.

Can you advise how to work with formatted expression that has JSON Path and static string to transform a valid JSON.

More examples for function `contains`

The documentation at http://jmespath.org/specification.html#contains demonstrates partial string matching on string input. The array input examples use only arrays of single character strings. This makes it unclear as to whether partial matching is done. I reality, partial matching is not performed against arrays. I'm not complaining about the matching. It makes sense to do it this way if you consider string input to be a "character array".

I'm providing a patch to improve clarity.

Using JMESPath to filter tree

{
    "a": [
        {
            "b": "foo",
            "c": "bar",
            "d": {
                "d_a": 123,
                "d_b": {}
            },
            "e": {
                "e_a": 123,
                "e_b": {}
            }
        },
        {
            "b": "foo",
            "c": "bar",
            "d": {
                "d_a": 123,
                "d_b": {}
            },
            "e": {
                "e_a": 123,
                "e_b": {}
            }
        }
    ]
}

I would love to use JMESPath to split it into two different documents (using two queries):

{
    "a": [
        {
            "b": "foo",
            "c": "bar",
            "d": {
                "d_a": 123,
                "d_b": {}
            }
        },
        {
            "b": "foo",
            "c": "bar",
            "d": {
                "d_a": 123,
                "d_b": {}
            }
        }
    ]
}

and

{
    "a": [
        {
            "b": "foo",
            "c": "bar",
            "e": {
                "e_a": 123,
                "e_b": {}
            }
        },
        {
            "b": "foo",
            "c": "bar",
            "e": {
                "e_a": 123,
                "e_b": {}
            }
        }
    ]
}

Is this possible?

If that fails... how can I filter by key name? See #20 (comment) (the "* TODO -- include an example of how to preserve the initial association of keys.")

Compliance levels

The compliance levels reported on the libraries page should be a bit more granular; the specification is changing over time and when it's updated libraries are no longer "fully compliant" (e.g. at the present point in time the Ruby library is lacking proper support for "and" and "or" expressions from JEP 9, so shouldn't really be listed as fully compliant).

Perhaps the specification could have versions instead and the libraries could instead indicate the version that they're compliant with? This would give users an indication of the features that they can expect to work and the features that they could expect not to.

How to filter a dictionary with `contains`?

{
  "group1": {
    "users": ["user1", "user2", "user3"]
  },
  "group2": {
    "users": ["user1", "user2"]
  },
  "group3": {
    "users": ["user3"]
  }
}

How to get groups which contain user3, i.e. ["group1", "group3"]?

I know about the | keys(@) pipe, but the question is how to filter a dictionary?

New Functions for JMESPath

I'd like to propose a few additional functions for inclusion in the JMESPath specification:

https://github.com/the-g-man/jmespath-ext

They're not complex to implement but they add a great deal of power - for instance in dealing with recursive or normalized data structures.

I've added documentation and compliance tests for each of the three functions.

Grep "key: value" by key

Is it possible to get all authors regardless of their location in a document?

In JSONPath it will be $..author, in jq ..|objects.author. What is the equivalent for JMESPath?

{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

Trying to understand it by comparing to known tools https://github.com/stedolan/jq/wiki/For-JSONPath-users

Lack of lexical token delimiter specification

It seems that the current JMESPath specification doesn't specify any lexical token delimiters, which leaves ambiguity and confusion.

For example, considering the following two grammar rules in the spec:

comparator-expression = expression comparator expression
raw-string            = "'" *raw-string-char "'"

Sub-rules are concatenated in the same way in the above two rules but clearly the first one allows white spaces between expression and comparator since we have the following official example in the examples page:

people[?age > `20`].[name, age]

while white spaces are not allowed between "'" and *raw-string-char since a raw-string is expected to be a single lexical token.

After studying RFC 4234, I foud the following statements in section 3.1:

   LINEAR WHITE SPACE: Concatenation is at the core of the ABNF parsing
   model.  A string of contiguous characters (values) is parsed
   according to the rules defined in ABNF.  For Internet specifications,
   there is some history of permitting linear white space (space and
   horizontal tab) to be freely and implicitly interspersed around major
   constructs, such as delimiting special characters or atomic strings.

   NOTE:

      This specification for ABNF does not provide for implicit
      specification of linear white space.

   Any grammar that wishes to permit linear white space around
   delimiters or string segments must specify it explicitly.  It is
   often useful to provide for such white space in "core" rules that are
   then used variously among higher-level rules.  The "core" rules might
   be formed into a lexical analyzer or simply be part of the main
   ruleset.

Shall we specify lexical token delimiters explicitly and distinguish lexical rules from grammar rules to eliminate the ambiguity?

definition of raw-string-char and compliance test are inconsistent

The definition says the following:

raw-string-char   = (%x20-26 / %x28-5B / %x5D-10FFFF) / preserved-escape /
                      raw-string-escape
preserved-escape  = escape (%x20-26 / %28-5B / %x5D-10FFFF)

However, the compliance test requires to handle the following:

'newline\n'

I think the definition should accept all characters except '.

Need the ability to unique a list

Need the ability to get a unique list of elements in an array (similar to UNIX uniq)

Say I have an array { "result": [ "G", "L", "G", "G", "L" ] }

uniq(result) yields [ "G", "L" ]

String manipulation examples?

can you provide examples of how we can do string manipulation such as I have a string "a/b" and instead of displaying "a/b", I want to display only "b". Possible to do?

Referencing a value from outer scope

Following the Filter Projections section of the tutorial, which filters all machines from a list that have a hard-coded argument value:

{
  "machines": [
    {"name": "a", "state": "running"},
    {"name": "b", "state": "stopped"},
    {"name": "b", "state": "running"}
  ]
}

machines[?state=='running'].name  ; ["a", "b"]

I was wondering if there was a way to reference another value from the object, for example:

{
  "wanted_state": "running",
  "machines": [
    {"name": "a", "state": "running"},
    {"name": "b", "state": "stopped"},
    {"name": "b", "state": "running"}
  ]
}

machines[[email protected]_state].name  ; can't reference "wanted_state"

The problem here is that the filter condition is evaluated in the context of one of the "machines" objects, and there is no way to reference the outer scope.

I did notice JEP 11, but is there a way to do this without it?

multiselect hash from nested dict without knowing key names doable?

Hello

I'd really appreciate some help with the following structure

[ {"a": [ { "b": { "foo": { "c": { "bar": { "value": "123" } } } } } ] } ]

Where I know the names of all the keys except for foo and bar, and would like to return those key names when 'value'=='123'

i.e. something like

[].a[0].b.[@1].c.[@2].[?(value=="123")].{ firstkey: @1.key, secondkey: @2.key }

No idea if what I'm asking is possible.

How to find all by key?

Could you please help me how to find all condition nodes recursively?

image

JSON example:

{
  "WHERE": {
    "AND": [
      {
        "condition": {
          "AND": [
            {
              "condition": {
                "name": "cond1"
              }
            },
            {
              "condition": {
                "name": "cond2"
              }
            }
          ],
          "name": "cond-group"
        }
      },
      {
        "condition": {
          "name": "cond3"
        }
      },
      {
        "condition": {
          "name": "cond4"
        }
      }
    ]
  }
}

I would like to find all conditions no matter where it is. Probably it should looks like *[?condition] or values(*)[?condition](non-rooted expressions).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.