15

How to construct json using JsonBuilder with key and value having same name?

import groovy.json.JsonBuilder

def userId = 12 // some user id obtained from else where.

def json = new JsonBuilder()
def root = json {
    userId userId
}
print json.toString()

Which produces the error

groovy.lang.MissingMethodException: No signature of method: java.lang.Integer.call() is applicable for argument types: (java.lang.Integer) values: [12] Possible solutions: wait(), any(), abs(), wait(long), wait(long, int), and(java.lang.Number)

Quoting the key does has no effect. Any idea how to make this work.

Edit:

I want the JSON to be like { userId: 12 }. Also, why does writing the key as string not work?

long userId = 12   
def json = new JsonBuilder()
def root = json {
    "userId" userId
}

The example provided is just a snippet. The situation is that I have a lot of controller actions, which has various variables already. Now I am adding a part where I am trying to create a JSON string with various values the variables hold. So it's not very practical to change existing variable names and if I could construct the JSON string with the same name, it would be more consistent. Writing accessor methods for all the variables I wanted is also not an elegant method. What I did at present is to use different naming scheme like user_id for userId but again, it's not consistent with rest of the conventions I follow. So I am looking for an elegant approach and the reason why JsonBuilder behaves in this manner.

In case of JavaScript,

var a = 1
JSON.stringify({a: a})    // gives "{"a":1}"

which is the expected result.

Dale K
  • 25,246
  • 15
  • 42
  • 71

3 Answers3

27
  • Declare accessors for the variable userId, if you need the JSON to look like {userId:12}

as

import groovy.json.JsonBuilder

def getUserId(){
    def userId = 12 // some user id obtained from else where.
}

def json = new JsonBuilder()
def root = json{
    userId userId
}
print json.toString()
  • If you need the JSON to look like {12:12} which is the simplest case:

then

import groovy.json.JsonBuilder

def userId = 12 // some user id obtained from else where.

def json = new JsonBuilder()
def root = json{
    "$userId" userId
}
print json.toString()
  • Just for the sake of the groovy script you can remove def from userId to get the first behavior. :)

as

import groovy.json.JsonBuilder

userId = 12

def json = new JsonBuilder()
def root = json{
    userId userId
}
print json.toString()

UPDATE

Local variables can also be used as map keys (which is String by default) while building JSON.

import groovy.json.JsonBuilder

def userId = 12 
def age = 20 //For example
def email = "abc@xyz.com"

def json = new JsonBuilder()
def root = json userId: userId, age: age, email: email

print json.toString() //{"userId":12,"age":20,"email":"abc@xyz.com"}
dmahapatro
  • 49,365
  • 7
  • 88
  • 117
  • Writing accessor methods for say 10 variables each in 100 methods is not very practical. But I understand that it resolves the situation, so does having a different name for the key. Do you know why we need an accessor? Why does Groovy behave like this? Other languages like JavaScript behaves as intended. Isn't this a bug? –  Oct 07 '13 at 14:40
  • I do not think it is a bug. Use map representation instead. See my update. @kadaj – dmahapatro Oct 07 '13 at 15:06
  • Yes I had found the solution independently. But, thanks for your effort. I will accept this as a right answer. –  Oct 07 '13 at 15:51
  • Thanks. In Jmeter 5.2.1, the code from your UPDATE section works for me in a JSR223 Sampler only if I replace this line def json = new JsonBuilder() with def json = new groovy.json.JsonBuilder() And this line: print json.toString() With: SampleResult.setResponseData(json.toString()); Maybe it helps someone. – JustNatural Oct 11 '21 at 18:05
  • do you know how I can append some other json object so that I make a more complex json structure? example: "emails":{ "email":[ { "email1": "test@test1.com", "isValid":true, }, { "email2": "test@test2.com", "isValid":true, } ] } – JustNatural Oct 11 '21 at 23:30
  • @JustNatural This answer might help. https://stackoverflow.com/a/17538765/2051952 – dmahapatro Oct 11 '21 at 23:45
  • You can go to my SO user profile and search for JsonBuilder to find additional use cases. – dmahapatro Oct 11 '21 at 23:46
4
import groovy.json.JsonBuilder
def userId = "12" // some user id obtained from else where.
def json = new JsonBuilder([userId: userId])
print json.toString()
moskiteau
  • 1,104
  • 11
  • 19
3

I was able to get a desired output using a different param to JsonBuilder's call() method. i.e., instead of passing in a closure, pass in a map.

Use def call(Map m) instead of def call(Closure c).

import groovy.json.JsonBuilder

long userId = 12
long z = 12
def json = new JsonBuilder()

json userId: userId,
     abc: 1,
     z: z     
println json.toString()    //{"userId":12,"abc":1,"z":12}