Search code examples
jsonrobotframeworkjsonpath

How to use fully functional JsonPath in RobotFramework?


Could you please recommend how to use JsonPath in the Robot Framework? It should supports multi-level query as following:

$.items[?(@.status.name="closed")].name

I'm seeking the way to make following work:

*** Variables ***
${json}         {"items":[{"name":"item1","status":{"id":1,"name":"opened"}},{"name":"item2","status":{"id":2,"name":"closed"}}]}
${json_path}    $.items[?(@.status.name="closed")].name
*** Test Cases ***
Get closed item
    ${names}=    Get Json Items    ${json}    ${json_path}
    Should be equal    ${names[0]}    item2

someting like this


Solution

  • This RF code does what you need but ONLY for provided json structure. From my point of view you should play with Get Json Value and prepare keywords you need. BTW, it is obvious that such json/string handling in RF is a bit complicated so I would rather write small Python library with keywords you need.

    *** Settings ***
    Library            Collections
    Library            HttpLibrary.HTTP
    
    *** Variables ***
    ${json}         {"items":[{"name":"item1","status":{"id":1,"name":"opened"}},{"name":"item2","status":{"id":2,"name":"closed"}}]}
    ${name}    ${EMPTY}
    ${result}    ${EMPTY}
    
    *** Test Cases ***
    Get Closed Item
        ${name}    Get Name By Status    ${json}    closed
        Should Be Equal As Strings    ${name}    item2
        ${name}    Get Name By Status    ${json}    opened
        Should Be Equal As Strings    ${name}    item1
    
    *** Keywords ***
    Get Name By Status
        [Arguments]    ${json}    ${status}
        [Return]    ${result}
        ${json}    Parse Json    ${json}
        :FOR    ${item}    IN    @{json["items"]}
        \    ${item}    Stringify Json    ${item}
        \    ${name}    Get Json Value    ${item}    /name
        \    ${name}    Parse Json    ${name}
        \    ${status_name}    Get Json Value    ${item}    /status/name
        \    ${status_name}    Parse Json    ${status_name}
        \    ${result}    Set Variable If    '${status_name}' == '${status}'    ${name}    ${result}
    

    Edit: based on comment below I would go for such python based code.

    JsonpathLibrary.py:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import json
    import jsonpath
    
    class JsonpathLibrary(object):
    
        def get_items_by_path(self, json_string, json_path):
            json_object = json.loads(json_string)
            match_object = jsonpath.jsonpath(json_object, json_path)
            match_string = json.dumps(match_object[0])
            return match_string
    

    RF code:

    *** Settings ***
    Library            JsonpathLibrary.py
    
    *** Variables ***
    ${json}         {"items":[{"name":"item1","status":{"id":1,"name":"opened"}},{"name":"item2","status":{"id":2,"name":"closed"}}]}
    ${json_path}    $.items[?(@.status.name=="closed")].name
    
    *** Test Cases ***
    Some Descriptive Name Here
        ${name}    Get Items By Path    ${json}    ${json_path}
        Should Be Equal As Strings    ${name}    "item2"