How to merge 2 JSON Arrays in Groovy? - arrays

Trying to merge 2 Json arrays into 1 in groovy.
def branchTags = new JsonBuilder()
branchTags branches, { String branch ->
tag branch
type 'b'
}
println(branchTags.toString())
//generates [{"tag":"Branch","type":"b"},{"tag":"Branch1","type":"b"}]
def releaseTags = new JsonBuilder()
releaseTags releases, {String release ->
tag release
type 'r'
}
println(releaseTags.toString())
//generates [{"tag":"Release","type":"r"},{"tag":"Rel1","type":"r"}]
/*def newTags = new JsonBuilder()
branchTags.each {k,v -> newTags.}*/
def slurper = new JsonSlurper()
def input = slurper.parseText(branchTags.toString())
def res = slurper.parseText(releaseTags.toString())
def joined = [input, res].flatten()
println joined.toString()
//this generates [{"tag":"Branch","type":"b"},{"tag":"Branch1","type":"b"}][{"tag":"Release","type":"r"},{"tag":"Rel1","type":"r"}]
I need:
[
{"tag":"Branch","type":"b"},
{"tag":"Branch1","type":"b"},
{"tag":"Release","type":"r"},
{"tag":"Rel1","type":"r"}
]
TIA,

in your case after you parsed json you have two arrays.
just use + to concatenate two arrays into one
import groovy.json.*
def branchTags = '[{"tag":"Branch","type":"b"},{"tag":"Branch1","type":"b"}]'
def releaseTags = '[{"tag":"Release","type":"r"},{"tag":"Rel1","type":"r"}]'
def slurper = new JsonSlurper()
def bArr = slurper.parseText(branchTags)
def rArr = slurper.parseText(releaseTags)
def res = bArr+rArr
println new JsonBuilder(res).toString()

Related

Can I create array by for loop in Kolin? the array is list listOfNames is inside a for loop but I can not use it outside the for loop

Can I create array by for loop in Kolin? the array is the list [listOfNames] is inside a for loop but I can not use it outside the for loop. I have to get strings from Excel in to array list and use it in main method.
fun readFromExcelFile(filepath: String): ArrayList<String> {
var listOfNames = ArrayList<String>()
val inputStream = FileInputStream(filepath)
var xlWb = WorkbookFactory.create(inputStream)
val rowNumber = 0
val columnNumber = 0
val xlWs = xlWb.getSheetAt(0)
for (i in 0..10) {
var currentCell = xlWs.getRow(i).getCell(columnNumber)
//println(currentCell)
listOfNames.add(currentCell.stringCellValue)
println(listOfNames)
}
//println(listOfNames)
return listOfNames
}
I would recommend that you return a List instead of an ArrayList and populate a MutableList in your function:
fun readFromExcelFile(filepath: String): List<String> {
var names = mutableListOf<String>()
val inputStream = FileInputStream(filepath)
var xlWb = WorkbookFactory.create(inputStream)
val rowNumber = 0 // you don't use this.
val columnNumber = 0
val xlWs = xlWb.getSheetAt(0)
for (i in 0..10) { // why isn't the range over the # of rows in the worksheet?
var currentCell = xlWs.getRow(i).getCell(columnNumber)
names.add(currentCell.stringCellValue)
}
return names
}

How to update the sql server's identity column using play2.6 slick3?

I got the following error when i try to run the sbt scala project using sql server,
[SQLServerException: Cannot update identity column 'ID'.]
I am using Play 2.6,Scala 2.12, Slick 3
my update function is,
def update(id: Long): Action[AnyContent] = Action.async { implicit request =>
topicForm.bindFromRequest.fold(
formWithErrors => Future.successful(BadRequest(html.editForm(id, formWithErrors))),
topic => {
val futureTopUpdate = dao.update(id, topic.copy(id = Some(id)))
futureTopUpdate.map { result =>
Home.flashing("success" -> "Topic %s has been updated".format(topic.code))
}.recover {
case ex: TimeoutException =>
Logger.error("Problem found in topic update process")
InternalServerError(ex.getMessage)
}
})
}
and the DAO:
override def update(id: Long, topic: Topic): Future[Int] =
try db.run(filterQuery(id).update(topic))
finally db.close
any idea?
You can show the filterQuery(id) implementation, something similar in a dao of us works well in this way:
override def update(id: Long, topic: Topic): Future[Int] = {
db.run(filterQuery(id).update(topic.copy(id))
}
Notice: topic.copy(id)
And filterQuery is:
def filterQuery(id: Int) = themes.filter(_.id === id)
We using Play 2.6,Scala 2.12, Slick 3 with MYSQL.
Update # 1:
-> Entity:
case class CategoryRow(id: Int, name: String, description: String)
-> Mapping:
trait CategoryMapping {
self: HasDatabaseConfigProvider[JdbcProfile] =>
import dbConfig.profile.api._
private[models] class CategoryTable(tag: Tag)
extends Table[CategoryRow](tag, "category") {
def id = column[Int]("id", O.AutoInc, O.PrimaryKey)
def name = column[String]("name", O.Length(TextMaxLength_250))
def description = column[String]("description", Nullable)
def categoryNameAgencyIndex = index("categoryName_agency_idx", (name, agencyId), unique = true)
override def * = (
id,
name,
description
) <> (CategoryRow.tupled, CategoryRow.unapply)
}
private[models] val Categories = TableQuery[CategoryTable]
private[models] val CategoriesInsertQuery = Categories returning Categories.map(_.id)
}
-> REPO
trait CategoryRepository {
//...
def update(id: Int, category: Category)(implicit agencyId: Int): Future[Int]
//...
}
-> REPOImpl:
#Singleton
class CategoryRepositoryImpl #Inject()(protected val dbConfigProvider: DatabaseConfigProvider)(implicit ec: RepositoryExecutionContext)
extends CategoryRepository with HasDatabaseConfigProvider[JdbcProfile] with CategoryMapping {
import dbConfig.profile.api._
//....
def update(id: Int, category: CategoryRow)(implicit agencyId: Int): Future[Int] =
db.run(filter(id).update(category.copy(id)))
private def filter(id: Int) = Categories.filter(_.id === id)
//....
}
-> RepositoryExecutionContex
class RepositoryExecutionContext #Inject()(actorSystem: ActorSystem) extends CustomExecutionContext(actorSystem, "repository.dispatcher")
and aplication.conf:
# db connections = ((physical_core_count * 2) + effective_spindle_count)
fixedConnectionPool = 5
repository.dispatcher {
executor = "thread-pool-executor"
throughput = 1
thread-pool-executor {
fixed-pool-size = ${fixedConnectionPool}
}
}
There's some more information about fold in Chapter 3.3 of Essential Slick.

Streaming text lines from multiple source files

I'm implementing a solution using akka-stream to read text lines from multiple files and came up with below impl:
def main(args: Array[String]): Unit = {
val g: Flow[String, Unit, NotUsed] = Flow.fromGraph(GraphDSL.create() {
implicit builder =>
import GraphDSL.Implicits._
val A = builder.add(doQuery)
val B = builder.add(analyzeResult)
A ~> B
FlowShape(A.in, B.out)
})
val files = Source(fileNames)
val lines = files.map(file =>
Source.fromIterator(() => Source.fromFile(file.getName, "UTF-8").getLines)
)
val done = lines.runForeach(g.runWith(_, Sink.ignore))
// implicit val ec = system.dispatcher
// done.onComplete(_ => system.terminate())
}
val fileNames: List[File] = ???
val doQuery = Flow[String]
.groupedWithin(1000, 100 millisecond)
.mapAsync(4)(x =>
Future[Seq[String]] {
synchronized {
// Do Something
Nil
}
}
)
val analyzeResult: Flow[Seq[String], Unit, NotUsed] = ???
Anyone can give comments/ feedbacks if there are better solutions?
I'd prefer not to have two Source's (the file list and the second one for the text lines from each file). Wondering how to just have one single Source (the list of files)...
TIA!
val g: Flow[File, Unit, NotUsed] = Flow.fromGraph(
GraphDSL.create() {
implicit builder =>
import GraphDSL.Implicits._
val A = builder.add(Flow[File]
.flatMapConcat {
Source.fromIterator(() =>
scala.io.Source.fromFile(s"${file.getAbsolutePath}", "UTF-8").getLines)
}
)
val B = builder.add(doQuery)
val C = builder.add(analyzeResult)
A ~> B ~> C
FlowShape(A.in, C.out)
}
)
val files = Source(fileNames)
val (_: NotUsed, done: Future[Done]) = g.runWith(files, Sink.ignore)
implicit val ec = system.dispatcher
done.onComplete(_ => system.terminate())

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.

Groovy ConfigSlurper Configure 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)
}

Resources