21

I have a Json file in which there is a field which I need to edit and save the file for next usage.

But the field which I need to edit is as shown below,

The value I need to assign fr the field is generated Randomly in run time which i'll be capturing in a variable and pass it to this json specific key "dp" then save the json.

The saved json will be used for REST POST url.

            {
                "p": "10",
                "v": 100,
                "vt": [
                    {
                        "dp": "Field to be edited"(integer value) , 
                  ]          
            }
Laurent Bristiel
  • 6,819
  • 34
  • 52
Vidya S
  • 239
  • 1
  • 2
  • 5
  • sorry, i dint get u. – Vidya S Feb 08 '16 at 04:26
  • Have you written any code to try and accomplish what you want to do? – Ian Feb 08 '16 at 04:26
  • no, i havent tried. As I am using ROBOT framework, i tried to use tool like ace , which changes json in run time.But i need a API inbuilt / the code piece to update a specific key value. – Vidya S Feb 08 '16 at 04:28
  • Do you know how to write code in python, or do you need a solution that doesn't involve writing code? – Bryan Oakley Feb 08 '16 at 12:18
  • You've posted invalid json data in your question. You have an open square bracket, and open curly bracket, then a close square bracket – Bryan Oakley Feb 08 '16 at 14:21
  • I just gave a stucture of code where to highlight the data need to be replaced. This is not actual code i am using. Yes I know to write code in python. – Vidya S Feb 09 '16 at 05:58

3 Answers3

38

The simplest solution would be to write a python keyword that can change the value for you. However, you can solve this with robot keywords by performing the following steps:

  1. convert the JSON string to a dictionary
  2. modify the dictionary
  3. convert the dictionary back to a JSON string

Convert the JSON string to a dictionary

Python has a module (json) for working with JSON data. You can use the evaluate keyword to convert your JSON string to a python dictionary using the loads (load string) method of that module.

Assuming your JSON data is in a robot variable named ${json_string}, you can convert it to a python dictionary like this:

${json}=    evaluate    json.loads('''${json_string}''')    json

With the above, ${json} now holds a reference to a dictionary that contains all of the json data.

Modify the dictionary

The Collections library that comes with robot has a keyword named set to dictionary which can be used to set the value of a dictionary element. In this case, you need to change the value of a dictionary nested inside the vt element of the JSON object. We can reference that nested dictionary using robot's extended variable syntax.

For example:

set to dictionary    ${json["vt"]}    dp=the new value

With that, ${json} now has the new value. However, it is still a python dictionary rather than JSON data, so there's one more step.

Convert the dictionary back to JSON

Converting the dictionary back to JSON is the reverse of the first step. Namely, use the dumps (dump string) method of the json module:

${json_string}=    evaluate    json.dumps(${json})    json

With that, ${json_string} will contain a valid JSON string with the modified data.


Complete example

The following is a complete working example. The JSON string will be printed before and after the substitution of the new value:

*** Settings ***
Library    Collections

*** Test Cases ***
Example
    ${json_string}=    catenate
    ...  {
    ...    "p": "10",
    ...    "v": 100,
    ...    "vt": {
    ...            "dp": "Field to be edited"
    ...          }
    ...  }

    log to console       \nOriginal JSON:\n${json_string}
    ${json}=             evaluate        json.loads('''${json_string}''')    json
    set to dictionary    ${json["vt"]}    dp=the new value
    ${json_string}=      evaluate        json.dumps(${json})                 json
    log to console       \nNew JSON string:\n${json_string}
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Sorry to hi-jack Bryan, this is similar to a problem I'm soon to tackle. It seems this could do for my needs, I'm assuming the remove from dictionary keyword preserves json document structure without much intentional thought? I also assume set to dictionary will update if the key exists already, yet add if it doesn't already exist? Again apologies for the hi-jack, figured I shouldn't add my own question with this being so closely related – shicky Feb 08 '16 at 16:14
  • 1
    @shicky: the best way to answer your question is for you to try it and see. Everything you asked, you can easily answer with a couple lines of code. – Bryan Oakley Feb 08 '16 at 16:18
  • this is certainly true Bryan, will hopefully free up some time this week or next and get it done. Thank you for your input – shicky Feb 09 '16 at 12:36
  • works like a charm Bryan, thanks for your extremely clear and well presented example above. Easy to tweak to my needs – shicky Mar 29 '16 at 14:29
  • 2
    This is a very good answer. In simple cases you don't even need to use the `json` module because simple JSON structures are also valid in Python and you can just use `| ${json} = | Evaluate | ${json_string} |`. Converting back to string ought to work with `| ${json_string} = | Convert To String | ${json} |`. – Pekka Klärck May 12 '16 at 13:50
  • 1
    @PekkaKlärck Not quite right since `true` is valid in json but not in Python (must be `True`) – Rod Sep 12 '16 at 19:15
  • In this example, how can you use the ordered_pairs_hook on json.loads to preserve the order? – pgtips Apr 18 '17 at 21:21
2

For reading and writing data to and from file I am using OperatingSystem library

${json} Get Binary File ${json_path}nameOfJsonFile.json

It works for me on API testing, to read .json and POST, like here

*** Settings ***
Library    Collections
Library    ExtendedRequestsLibrary 
Library    OperatingSystem
*** Variables ***  
${uri}    https://blabla.com/service/
${json_path}    C:/home/user/project/src/json/
*** Test Cases ***
Robot Test Case  
   Create Session    alias    ${uri}    
   &{headers}  Create Dictionary  Content-Type=application/json; charset=utf-8
   ${json}  Get Binary File  ${json_path}nameOfJsonFile.json
   ${resp}    Post Request    alias    data=${json}    headers=${headers}
   Should Be Equal As Strings    ${resp.status_code}    200
idomoni
  • 63
  • 9
0

For integer values in JSON, the other answers did not work for me. This worked:

${json}=    Catenate    {    "p": "10",    "v": 100,    "vt": {    "dp": "Field to be edited"   }    }
${value}    Set Variable    2    #the value you want
${value}    Convert To Integer    ${value}
${json}=    Evaluate    json.loads('''${json}''')    json
Set To Dictionary    ${json["vt"]}    dp=${value}
${json}=    Evaluate    json.dumps(${json})    json
Log    ${json}

Convert To Integer was required, otherwise the value is still in string "${value}"

codemech
  • 1
  • 1