2

I am trying to run code dynamically in groovy. I have someNode[0], which is the value, in variable var1

I then added double quotes to it like this

var2 = "\""+var1+"\""

then I tried to run this

request.abc."$var2"=Value

I saw here that something of this sort can be done on properties and methods. But the above code is not working. Giving me error

An error occurred [Cannot set property '"someNode[0]"' on null object], see error log for details

Any help is appreciated. Thanks.

Edit Heres a snippet of my request

{
   "app":{
      "bundle":"531323947",
      "cat":[
         "IAB1",
         "IAB9",
         "IAB9-30",
         "entertainment",
         "games"
      ],
      "id":"agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA",
      .
      .

The field I am trying to manipulate is cat[0], which is IAB1 (I just used abc and someNode[0] in the code that i wrote above but actually they are app and cat[0])

Also, I parsed the request with jsonslurper befor running the above code

Thank you for your help

Community
  • 1
  • 1
user1207289
  • 3,060
  • 6
  • 30
  • 66
  • how about var2 = var1 request.abc."$var2"=Value – V H Sep 26 '14 at 13:50
  • @vahid Thank you for response. I tried to ran `var2 = var1` `request.abc."$var2"=Value` but its giving me same error `An error occurred [Cannot set property 'someNode[0]' on null object], see error log for details` – user1207289 Sep 26 '14 at 14:04
  • usually the [0] tells groovy to return the first element of any array - It may be related to this - is there no way you can remove this and add it after u got your value set ? – V H Sep 26 '14 at 14:09
  • could you show us your request. and @vahid is right, while you can access by string, it might not be that easy for an array. your code above might allready fail, because there is no "abc" in the "request". – cfrick Sep 26 '14 at 14:12
  • @cfrick I edited the question to show the request. thank you – user1207289 Sep 26 '14 at 14:28

2 Answers2

2

One way to do this, is by Eval

def request =[
"app":[
    "bundle":"531323947",
    "cat":[
            "IAB1",
            "IAB9",
            "IAB9-30",
            "entertainment",
            "games"
    ],
]
]

assert request.app.cat[0]=='IAB1'
def var = 'request.app.cat[0]'
Eval.me('request', request, "$var = 'new value'")
assert request.app.cat[0]=='new value'
cfrick
  • 35,203
  • 6
  • 56
  • 68
  • You should really be careful with feeding `Eval` with user content! If this is feeded via some web interface with user content, i'd rather go with a parser. – cfrick Sep 26 '14 at 14:41
  • 1
    I tried the above solution but getting this error `An error occurred [startup failed:Script1.groovy: 1:[parsed_MessageBody.app.cat[0]] is a constant expression, but it should be a variable expression at line: 1 column: 33. File: Script1.groovy @ line 1, column 33. 'parsed_MessageBody.app.cat[0]' = 'Value'^1 error], see error log for details` . Not sure whats going on. Any idea? – user1207289 Sep 26 '14 at 16:59
  • 1
    @user1207289 `'parsed_MessageBody.app.cat[0]' = 'Value'` looks wrong. it should be `parsed_MessageBody.app.cat[0] = 'Value'` (no quotes on the first string) – cfrick Sep 27 '14 at 11:40
  • thank you for pointing out, I'll try with the change and post the result. – user1207289 Sep 29 '14 at 14:56
  • this is working fine now. Thanks a lot , though I still have to find out what `Eval.me('request', request, "$var = 'new value'")` is doing. I know `eval` but gather understanding on the first argument you passed in eval. 2nd and 3rd I kind of understand. – user1207289 Sep 30 '14 at 17:19
  • @user1207289 You telling Eval, that there is variable with the name `request` and the value of your request variable. – cfrick Sep 30 '14 at 17:47
1

You are accessing/updating values from a map and a list. The request.app node will be a map, the request.app.cat node will be a list. Getting and setting the values in a map can be done in many different ways:

  1. Use the put & get methods directly.
  2. Use brackets [].
  3. Use missing properties as map keys (i.e. the way you are using it).

For what you want to achieve, i.e. to access values from variable keys, it is much easier to use method 1 or 2 instead of method 3 with a variable inside a GString.

Example using brackets:

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper

def request = new JsonSlurper().parseText '''{
        "app":{
            "bundle":"531323947",
            "cat":[
                "IAB1",
                "IAB9",
                "IAB9-30",
                "entertainment",
                "games"
            ],
            "id":"agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA"
        }
    }'''

def level0 = 'app'
def level1 = 'cat'

def node = request[level0][level1]

assert request instanceof Map
assert node instanceof List
assert node[0] == 'IAB1'

node[0] = 'new value'
assert node[0] == 'new value'

println new JsonBuilder(request).toPrettyString()

Output:

{
    "app": {
        "cat": [
            "new value",
            "IAB9",
            "IAB9-30",
            "entertainment",
            "games"
        ],
        "id": "agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA",
        "bundle": "531323947"
    }
}
Steinar
  • 5,860
  • 1
  • 25
  • 23
  • The only issue I am having implemeting this in my case is that `cat[0]` is in a variable. Looks to me an overhead to again parse `cat[0]`. I cant hard code like this `def level1 = 'cat'` and `node[0] = 'new value'` . But it seems to me a good approach for any other cases. I'll accept the below answer as its perfectly fitting in my code. And I'll up your answer because I learned from it. And thank you again for your input. – user1207289 Sep 30 '14 at 17:15