Groovy ConfigSlurper Configure Arrays - arrays

I am trying to create a config that would look something like this:
nods = [
nod {
test = 1
},
nod {
test = 2
}
]
and then use configSlurper to read it but the "node" objects appear to be null after the read.
Here is my code:
final ConfigObject data = new ConfigSlurper().parse(new File("config.dat").toURI().toURL())
println data.nods
and the output:
[null, null]
What am I doing wrong?
Thanks!

It think I resolved it this way:
config {
nods = [
['name':'nod1', 'test':true],
['name':'nod2', 'test':flase]
]
}
And then using it like:
config = new ConfigSlurper().parse(new File("config.groovy").text)
for( i in 0..config.config.nods.size()-1)
println config.config.nods[i].test
Hope this helps someone else!!

You have to be careful when using ConfigSlurper when doing this sort of thing.
For example your solution will actually produce the following output:
true
[:]
If you look carefully you will notice that there is a typo on the second array value flase instead of false
The following:
def configObj = new ConfigSlurper().parse("config { nods=[[test:true],[test:false]] }")
configObj.config.nods.each { println it.test }
should produce the correct result:
true
false

I tried to parse with ConfigSlurper something like this:
config {sha=[{from = 123;to = 234},{from = 234;to = 567}]}
The array "sha" was far from what expected.
To get "sha" as an array of ConfigObjects I used a helper:
class ClosureScript extends Script {
Closure closure
def run() {
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.delegate = this
closure.call()
}
}
def item(closure) {
def eng = new ConfigSlurper()
def script = new ClosureScript(closure: closure)
eng.parse(script)
}
this way I get an array of ConfigObjects:
void testSha() {
def config = {sha=[item {from = 123;to = 234}, item {from = 234;to = 567}]}
def xx = item(config)
assertEquals(123, xx.sha[0].from)
}

Related

display content-type(Strategy) fields value in the form of array in groovy

I have a snippets of groovy code (inside strategy.groovy file) as shown below in which I want to display the output in the form of desired array.
The content-type Strategy (in crafter) has the following fields:
Title English (title_en_t)
Title French (title_fr_t)
Description English (description_en_t)
Description French (description_fr_t)
Players (players_o)
groovy code (inside strategy.groovy file):
private createStrategyElement(rootStrategy, ctx) {
Element strategy = new DefaultElement("strategy")
strategy.addElement("players_o.first_name_s").text = rootStrategy.players_o.item.component.first_name_s != null ? rootStrategy.players_o.item.component.first_name_s : "" //Line A
strategy.addElement("players_o.last_name_s").text = rootStrategy.players_o.item.component.last_name_s != null ? rootStrategy.players_o.item.component.last_name_s : "" //Line B
return strategy
}
Line A and Line B display the o/p in the following fashion:
current o/p:
players_o.first_name_s: "[John, The]"
players_o.last_name_s: "[Cena, Undertaker]"
PROBLEM STATEMENT:
I am wondering what changes I need to do in the groovy code above at Line A and Line B so that it displays the o/p in this fashion:
DESIRED O/P:
players: [{
"item": [
{
"first_name_s": "John",
"last_name_s": "Cena"
},
{
"first_name_s": "The",
"last_name_s": "Undertaker"
}
]
}]
don't know what is the crafter-cms. and you have not provided the input for your code.
i found DefaultElement and addElement in dom4j library - so i assume it's the one used in crafter-cms
https://dom4j.github.io/javadoc/2.0.1/org/dom4j/tree/DefaultElement.html
you are expecting json in output but dom4j used to work with xml...
however. just a try
private createStrategyElement(rootStrategy, ctx) {
Element strategy = new DefaultElement("strategy")
def players = strategy.addElement('players')
for(i in rootStrategy.players_o.item.component){
def item = players.addElement('item')
item.addElement('first_name_s').text = i.first_name_s
item.addElement('last_name_s').text = i.last_name_s
}
return strategy
}
the following code i used to debug it in standard groovy console:
#Grab(group='org.dom4j', module='dom4j', version='2.1.3')
import org.dom4j.tree.DefaultElement
import org.dom4j.Element
import org.dom4j.io.XMLWriter
import org.dom4j.io.OutputFormat
def rootStrategy=[
players_o:[
item:[
component:[
[
first_name_s:'John',
last_name_s: 'Cena',
],
[
first_name_s:'The',
last_name_s: 'Undertaker'
],
]
]
]
]
private createStrategyElement(rootStrategy, ctx) {
Element strategy = new DefaultElement("strategy")
def players = strategy.addElement('players')
for(i in rootStrategy.players_o.item.component){
def item = players.addElement('item')
item.addElement('first_name_s').text = i.first_name_s
item.addElement('last_name_s').text = i.last_name_s
}
return strategy
}
println new StringWriter().with{w->
new XMLWriter(w, OutputFormat.createPrettyPrint()).write( createStrategyElement(rootStrategy,null) )
w.toString()
}

Search array for a value [swift]

Just started learning swift, spent a few hours trying to figure this out by searching here but no luck so far.
I have an array, created like this:
class ProbabilitiesClass {
var list = [Odds]()
init() {
list.append(Odds(dateInit: -35, oddsTodayInit: "0,01", sevenDaysInit: "0,2"))
list.append(Odds(dateInit: -34, oddsTodayInit: "0,01", sevenDaysInit: "0,3"))
list.append(Odds(dateInit: -33, oddsTodayInit: "0,02", sevenDaysInit: "0,4"))
I want to search first parameter of this array for an integer and return its index.
Tried this
if let i = Odds.firstIndex(where: { $0.hasPrefix(differenceInDays) }) {
print("index is \([i])")
}
It returns error:
Type 'Odds' has no member 'firstIndex'
The end goal is to return second and third parameters of that index.
Update: I defined Odds like this:
import Foundation
class Odds {
let dateText : Int
let oddsToday : String
let odds7Days : String
init(dateInit: Int, oddsTodayInit: String, sevenDaysInit : String) {
dateText = dateInit
oddsToday = oddsTodayInit
odds7Days = sevenDaysInit
}
}
You could do it like so:
let p = ProbabilitiesClass()
let differenceInDays = -34
if let i = p.list.firstIndex(where: { $0.dateText == differenceInDays }) {
print("index is \([i])") //index is [1]
}
Look for the index in the list property of an instance of ProbabilitiesClass. And like the error message says: The class Odds is not an array to use the method firstIndex(where:) on it.
If you want to use the properties of the first element which has its dateInit equal to differenceInDays, then you could do it like so:
if let first = p.list.first(where: { $0.dateText == differenceInDays }) {
print("oddsTodayInit =", first.oddsToday)
print("sevenDaysInit =", first.odds7Days)
}
It uses this function first(where:).

Lua multidimensional table call

I seem to be having a problem with multidimensional tables (arrays?) on Lua. I have one that looks something like this:
arr =
{
"stats" = {
"23" = {
"1" = {
"account_id" = "10",
"info" = {
"name" = "john"
}
}
}
}
}
and whenever I try to access some info using like:
local entry = "23"
print(arr['stats'][entry]['1'])
or
print(arr['stats'][entry]['1']['info']['name'])
I get nil values, is mixing strings with variables when calling tables even allowed? any idea what I'm doing wrong?
It seems that lua does not accepts things like
arr = { "string" = "value"}
so, either you do
arr = { string = "value"}
or you do
arr = {["string"] = value}
That way, your table must be rewritten as this, in order to run on lua 5.3 interpreter:
arr =
{
stats =
{
["23"] =
{
["1"] =
{
account_id = "10",
info =
{
name = "john"
}
}
}
}
}
doing this, your line
print(arr['stats'][entry]['1']['info']['name'])
runs fine.
Also, it is not good practice to use brackets when you can use a dot. It is not that your script will not run otherwise, but the code gets a lot more legible and easier to debug if you wirte that line like this:
print(arr.stats[entry]['1'].info.name)
Hope that helps...

JSON with array and non-array data with Groovy JsonBuilder

I need to create a JSON string in my Groovy script which has some elements that are array and some which are not. For example the below..
{
"fleet": {
"admiral":"Preston",
"cruisers": [
{"shipName":"Enterprise"},
{"shipName":"Reliant"}
]
}
}
I found this post but the answers either didn't make sense or didn't apply to my example.
I tried the below in code...
def json = new groovy.json.JsonBuilder()
def fleetStr = json.fleet {
"admiral" "Preston"
cruisers {
{shipName: "[Enterprise]"}, {shipName: "[Reliant]"}
}
}
But it gives an exception...
Ambiguous expression could be either a parameterless closure expression or an isolated open code block
In Groovy, the {} syntax is used for closures. For objects in JSON, you want to use the map syntax [:], and for lists, the list syntax []:
def json = new groovy.json.JsonBuilder()
def fleetStr = json.fleet {
"admiral" "Preston"
cruisers( [
[shipName : "[Enterprise]"],
[shipName: "[Reliant]"]
])
}
assert json.toString() ==
'{"fleet":{"admiral":"Preston","cruisers":[{"shipName":"[Enterprise]"},{"shipName":"[Reliant]"}]}}'
Update: as per your follow-up, you need to use the same list syntax [] outside the "[Enterprise]" and "[Reliant]" strings:
def json = new groovy.json.JsonBuilder()
def fleetStr = json.fleet {
"admiral" "Preston"
cruisers( [
[shipName : ["Enterprise"]],
[shipName: ["Reliant"]]
])
}
assert json.toString() ==
'{"fleet":{"admiral":"Preston","cruisers":[{"shipName":["Enterprise"]},{"shipName":["Reliant"]}]}}'

How can I use map in this kind of situation in grails?

I need to display server info that are running up on ec2. I have managed to display them as a json, but now i only need to display certain fields. The following shows how I am displaying the statusCode and RunType. Similar concept is applied for other fields.
def check = reservations.each { Reservation reservation ->
reservation.instances.each() { Instance instance ->
def code = instance.state
def StatusCode = code.code
//Get other values
instance.tags.each() { Tag tag5 ->
def KeyName2 = tag5.key;
if (KeyName2 == 'RunType') {
def RunType = tag5.value;
}
}
}
instance.tags.each() { Tag tag2 ->
def KeyName2 = tag2.key;
if (KeyName2 == 'RunType') {
def value2 = tag2.value; }
}
instance.tags.each() { Tag tag3 ->
def KeyName3 = tag3.key;
if (KeyName3 == 'StartedBy') {
def value = tag3.value;
}
}
I wanna obtain something like this to display in my gsp page and loop it for every server.
def map = [StatusCode:"80", RunType:"Always", value"test", value2:"abc"]
But not sure on how to add values to the map when i obtain them thru the code
You might be able to use this:
def result = reservations.collectMany { reservation ->
reservation.instances.collect { instance ->
[ StatusCode: instance.code,
RunType : instance.tags.find { it.key == 'RunType' }?.value,
StartedBy : instance.tags.find { it.key == 'StartedBy' }?.value ]
}
}
Updated after the update to the question
From the code it looks like, a statusCode can have multiple value5. If that is not the case then you can do something like :
def myList = []
def check = reservations.each { Reservation reservation ->
reservation.instances.each() { Instance instance ->
def statusCode = instance.state?.code
def value5 = instance.tags?.find{it.key == 'RunType'}?.value
myList << ["StatusCode": statusCode, "RunType": value5 ]
}
}
Note the inner loop is simplified. I am not sure whether it meets your use case scenario since there are inner loops. If you think the map needs to be moved one level down inside the loop then you maintain a list of the key-value pairs (or the map) in the list as well.
The logic can be over-simplified using groovy's collect and inject functionality.

Resources