json - Groovy JsonBuilder strange behavior when toString() -
i need create json use body in http.request
. i'm able build dynamically json, noticed strange behavior when calling builder.tostring()
twice. resulting json totally different. i'm think related kind of buffer or so. i've been reading documentation can't find answer. here code test.
import groovy.json.jsonbuilder def builder = new jsonbuilder() def map = [ cata: ["cata-element1", "cata-element2"], catb:[], catc:["catc-element1"] ] def = map.inject([:]) { res, k, v -> def b = v.inject([:]) {resp, -> resp[i] = k resp } res += b } println def root = builder.query { bool { must a.collect{ k, v -> builder.match { "$v" k } } } should([ builder.simple_query_string { query "text" } ]) } println builder.tostring() println builder.tostring()
this print following lines. pay attention last 2 lines
[cata-element1:cata, cata-element2:cata, catc-element1:catc] {"query":{"bool":{"must":[{"match":{"cata":"cata-element1"}},{"match":{"cata":"cata-element2"}},{"match":{"catc":"catc-element1"}}]},"should":[{"simple_query_string":{"query":"text"}}]}} {"match":{"catc":"catc-element1"}}
in code can send first tostring()
result variable , use when needed. but, why change when invoking more 1 time?
i think happening because using builder
inside closure bool
. if make print builder.content
before printing result (buider.tostring()
calling jsonoutput.tojson(builder.content)
) get:
[query:[bool:consolescript54$_run_closure3$_closure6@294b5a70, should:[[simple_query_string:[query:text]]]]]
adding println builder.content
bool
closure can see builder.content
modified when closure evaluated:
def root = builder.query { bool { must a.collect{ k, v -> builder.match { "$v" k println builder.content } } } should([ builder.simple_query_string { query "text" } ]) } println jsonoutput.tojson(builder.content) println builder.content
the above yields:
[query:[bool:consolescript55$_run_closure3$_closure6@39b6156d, should:[[simple_query_string:[query:text]]]]] [match:[cata:cata-element1]] [match:[cata:cata-element2]] {"query":{"bool":{"must":[{"match":{"cata":"cata-element1"}},{"match":{"cata":"cata-element2"}},{"match":{"catc":"catc-element1"}}]},"should":[{"simple_query_string":{"query":"text"}}]}} [match:[catc:catc-element1]]
you can avoid different builder closure inside:
def builder2 = new jsonbuilder() def root = builder.query { bool { must a.collect{ k, v -> builder2.match { "$v" k } } } should([ builder.simple_query_string { query "text" } ]) }
or better:
def root = builder.query { bool { must a.collect({ k, v -> ["$v": k] }).collect({[match: it]}) } should([ simple_query_string { query "text" } ]) }
Comments
Post a Comment