groovy> def d = '{"a": 1, "b": {"bb": 2}}, "c": 3}'
groovy> def m = new groovy.json.JsonSlurper().parseText(d)
groovy> println m
groovy> println m instanceof Map
[a:1, b:[bb:2]]
true
Obviously there is a redundant } at key b, but groovy can also parse, and key c lost. How to throw exception?
unfortunately it's a feature of groovy json slurper...
the only way i found as workaround - when you want to validate json without external json parser:
import groovy.json.*
def d = '{"a": 1, "b": {"bb": 2}}, "c": 3}'
def m = new JsonSlurper().parseText('['+d+']')[0] //parse as array and get first element
Related
import groovy.json.JsonSlurper
def ver = "['a', 'b', 'c']"
def jsonSlurper = new JsonSlurper()
def ver_list = jsonSlurper.parseText(ver)
println ver_list
This is what I'm doing. I want to iterate over ver_list. And it seems difficult to find a solution for it.
This is the error when I print ver_list:
Caught: groovy.json.JsonException: Unable to determine the current character, it is not a string, number, array, or object
The current character read is ''' with an int value of 39
Unable to determine the current character, it is not a string, number, array, or object
line number 1
index number 1
['a', 'b', 'c']
.^
groovy.json.JsonException: Unable to determine the current character, it is not a string, number, array, or object
The current character read is ''' with an int value of 39
Unable to determine the current character, it is not a string, number, array, or object
line number 1
index number 1
['a', 'b', 'c']
the valid json strings must be double-quoted.
so change in your code this line and it should work:
def ver = '["a", "b", "c"]'
however if you need to parse not a valid json you could try LAX parser.
then even the following string could be parsed
import groovy.json.JsonSlurper
import groovy.json.JsonParserType
def ver = "[a, 'b', 001]"
def jsonSlurper = new JsonSlurper().setType( JsonParserType.LAX )
def ver_list = jsonSlurper.parseText(ver)
println ver_list
Suppose variable b=2 and a stringified json
j = '{"b": "#{b}", "c": null}'
The desired result is:
{
"b" => "2",
"c" => nil
}
My observation:
Since json string contains null, we can not eval it because ruby will say undefined variable or method null. Also, I don't want to replace null with nil.
The only option left is to parse and evaluate.
So I tried the following:
eval(JSON.parse(j).to_s)
which results to
{
"b" => "\#{b}"
}
Please help to achieve desired result?
it should be like this: j = "{'b': '#{b}', 'c': null}"
UPDATE:
Sorry. It should be like this
b = 2
JSON.parse("{ \"b\": \"#{b}\", \"c\": null }")
How do I convert an arbitrary Groovy map / list to the config style DSL syntax that Groovy provides?
Example:
def config = [
'test': 'lalala',
'nestedObject': [
foo1: 'foo1 val',
foo2: 'foo2 val',
nested2: [
anInt: 5,
anArray: ['a', 'b', 'c'],
anIntArray: [1, 2, 3]
]
]
]
To something like:
test = 'lalala'
nestedObject {
foo1 = 'foo1 val'
foo2 = 'foo2 val'
nested2 {
anInt = 5
anArray = ['a', 'b', 'c']
anIntArray = [1, 2, 3]
}
}
UPDATE:
Re-appropriating this post to explicitly ask for a dynamic/generalized solution.
This makes it a unique question and unlike the following which assumes a known map at its initialization state: How to create ConfigObject using only nested maps in Grails?
If you know the nested Map structure in advance, your solution will work. If you need to do this on an unknown arbitrary nested Map structure, try something like this:
import groovy.util.ConfigObject
def mapToConfig
mapToConfig = { Map map ->
map.collectEntries { k, v ->
v instanceof Map ? [(k):mapToConfig(v)] : [(k):v]
} as ConfigObject
}
Given your input and the above closure definition, the following print statement:
println mapToConfig(config).prettyPrint()
Yields this output:
test='lalala'
nestedObject {
foo1='foo1 val'
foo2='foo2 val'
nested2 {
anInt=5
anArray=['a', 'b', 'c']
anIntArray=[1, 2, 3]
}
}
Just convert each Map into a ConfigObject and then pretty-print it:
import groovy.util.ConfigObject
def config = [
'test': 'lalala',
'nestedObject': [
foo1: 'foo1 val',
foo2: 'foo2 val',
nested2: [
anInt: 5,
anArray: ['a', 'b', 'c'],
anIntArray: [1, 2, 3]
] as ConfigObject
] as ConfigObject
] as ConfigObject
println config.prettyPrint()
All credit goes to: How to create ConfigObject using only nested maps in Grails?
(I just wanted people to know you can do this outside of Grails and initially I didn't realize how the pretty printing was invoked. I was confused with JsonOutput.prettyPrint())
Thanks #Steinar
Given: myList = [request:request,actions:actions] where request is an object and actions is a map.
Trying to get something like this:
{data:[
{a:'a',b:'b',actions:[c:'c',d:'d']},..
]}
where a and b are request properties while c and d are actions are map entries.
using:
render(contentType:"text/json"){
data = array {
myList.each { obj->
rqst = {
obj.request
actions = {actions: obj.actions}
}
}
}
}
obviously syntax here is wrong... but perhaps close?
I think the following accomplishes what you were looking for. PropsHolder is a simple inner class with two (a, b) properties
def request = new PropsHolder()
request.a = "a"
request.b = "b"
def actions = [c: "c", d: "d"]
def myList = [request: request, actions: actions]
render(contentType:"text/json")
{
[data: [
a: myList.request.a,
b: myList.request.b,
actions: myList.actions
]
]
}
The json result looks like this when output to a web page:
{"data":{"a":"a","b":"b","actions":{"c":"c","d":"d"}}}
I wasn't quite sure with the [a, b, actions] collection if you were looking for a map or an array. Tough to tell from the output, I went with map.
I have one scenario to sort the values based domain class property. This property may acept all numeric and alphanumeric values in the format XXX-1.
def res= Book.listOrderByName()
or
def res = Book.findAll("from Book order by name")
Giving the same result and result is displaying first numbers latter alphanumeric values.
My problem is :
these values are sorted before -.
for example i have AB-1,AB-2,...AB-12.
The result is displayed as AB-1,AB-10.AB-11,AB-2,AB-3,..AB-9
I have result like:
[18001,18002,2,300,3901,42,9,AB-1,AB-10,AB-2,AB-21,AB-9]
It should display the value as:
[2,9,42,300,3901,18001,18002,AB-1,AB-2,AB-9,AB-10,AB-21]
Run this in the Groovy console:
List sort(list) {
list.sort {a, b ->
a.class == b.class ? a <=> b : a instanceof Integer ? -1 : 1
}
}
// Test the sort function
def list = [18001,18002,2,300,3901,42,9,'AB-1','AB-10','AB-2','AB-21','AB-9']
assert sort(list) == [2, 9, 42, 300, 3901, 18001, 18002, 'AB-1', 'AB-10', 'AB-2', 'AB-21', 'AB-9']