Xpath like query for nested python dictionaries

后端 未结 10 1621
情话喂你
情话喂你 2020-12-02 15:45

Is there a way to define a XPath type query for nested python dictionaries.

Something like this:

foo = {
  \'spam\':\'eggs\',
  \'morefoo\': {
               


        
相关标签:
10条回答
  • 2020-12-02 16:12

    Another alternative (besides that suggested by jellybean) is this:

    def querydict(d, q):
      keys = q.split('/')
      nd = d
      for k in keys:
        if k == '':
          continue
        if k in nd:
          nd = nd[k]
        else:
          return None
      return nd
    
    foo = {
      'spam':'eggs',
      'morefoo': {
                   'bar':'soap',
                   'morebar': {'bacon' : 'foobar'}
                  }
       }
    print querydict(foo, "/morefoo/morebar")
    
    0 讨论(0)
  • 2020-12-02 16:12

    Is there any reason for you to the query it the way like the XPath pattern? As the commenter to your question suggested, it just a dictionary, so you can access the elements in a nest manner. Also, considering that data is in the form of JSON, you can use simplejson module to load it and access the elements too.

    There is this project JSONPATH, which is trying to help people do opposite of what you intend to do (given an XPATH, how to make it easily accessible via python objects), which seems more useful.

    0 讨论(0)
  • 2020-12-02 16:14

    dict > jmespath

    You can use JMESPath which is a query language for JSON, and which has a python implementation.

    import jmespath # pip install jmespath
    
    data = {'root': {'section': {'item1': 'value1', 'item2': 'value2'}}}
    
    jmespath.search('root.section.item2', data)
    Out[42]: 'value2'
    

    The jmespath query syntax and live examples: http://jmespath.org/tutorial.html

    dict > xml > xpath

    Another option would be converting your dictionaries to XML using something like dicttoxml and then use regular XPath expressions e.g. via lxml or whatever other library you prefer.

    from dicttoxml import dicttoxml  # pip install dicttoxml
    from lxml import etree  # pip install lxml
    
    data = {'root': {'section': {'item1': 'value1', 'item2': 'value2'}}}
    xml_data = dicttoxml(data, attr_type=False)
    Out[43]: b'<?xml version="1.0" encoding="UTF-8" ?><root><root><section><item1>value1</item1><item2>value2</item2></section></root></root>'
    
    tree = etree.fromstring(xml_data)
    tree.xpath('//item2/text()')
    Out[44]: ['value2']
    

    Json Pointer

    Yet another option is Json Pointer which is an IETF spec that has a python implementation:

    • https://github.com/stefankoegl/python-json-pointer

    From the jsonpointer-python tutorial:

    from jsonpointer import resolve_pointer
    
    obj = {"foo": {"anArray": [ {"prop": 44}], "another prop": {"baz": "A string" }}}
    
    resolve_pointer(obj, '') == obj
    # True
    
    resolve_pointer(obj, '/foo/another%20prop/baz') == obj['foo']['another prop']['baz']
    # True
    
    >>> resolve_pointer(obj, '/foo/anArray/0') == obj['foo']['anArray'][0]
    # True
    
    
    0 讨论(0)
  • 2020-12-02 16:15

    Not exactly beautiful, but you might use sth like

    def xpath_get(mydict, path):
        elem = mydict
        try:
            for x in path.strip("/").split("/"):
                elem = elem.get(x)
        except:
            pass
    
        return elem
    

    This doesn't support xpath stuff like indices, of course ... not to mention the / key trap unutbu indicated.

    0 讨论(0)
提交回复
热议问题