How to make GroupBy result list to new Map in Webflux - kotlin

How to make GroupBy result list to new Map in Webflux
There is my input list and expect result. then what should I do to make the result.
// expect
{
"timestamp": "2019-06-13T00:00:00.000",
"result": {
"first": 1,
"second": 2,
"third": 3
}
}
// input list
[
{
"timestamp": "2019-06-13T00:00:00.000",
"first": 1
},
{
"timestamp": "2019-06-13T00:00:00.000",
"second": 2
},
{
"timestamp": "2019-06-13T00:00:00.000",
"third": 3
}
]
val Flux.fromIterable(list)
.groupBy{it.timestamp}
.concatMap { groupItem ->
// here!! I want to make `group by result list to new Map``
Result(timestamp = groupItem.key()!!, Item(first = ?, second = ?, third =?))
}

I figured it out.
Flux.merge(first, second, thrid)
.groupBy { it.timestamp }
.concatMap {
it.map { item ->
val container = mutableMapOf<String, Any>()
if (item is firstEntity) {
container["first"] = item.result.count
container["timestamp"] = it.key()!!
}
if (item is secondEntity) container["second"] = item.result.count
if (item is thridEntity) container["thrid"] = item.result.count
container
}.reduce { acc, current ->
acc.putAll(current)
acc
}
}
.map {
val first = (it["first"] ?: 0) as Int
val second = (it["second"] ?: 0) as Int
val thrid = (it["thrid"] ?: 0) as Int
val timestamp = (it["timestamp"] ?: "") as String
// somthing!!
}

Related

I am struggling in this dataweave language [duplicate]

This question already has answers here:
dataweave transformation
(3 answers)
Closed 4 months ago.
Input :
{
"payload": {
"Field_X": "X",
"Field_Y": 10,
"Field_Z": "Z",
"Field_W" : {
"sub_1": "value_1",
"sub_2": true,
"sub_3": "value_3"
}
},
"mapper": {
"A": "<payload.Field_X>",
"B": "<payload.Field_Y>",
"C": "Fields or text not mapped to payload",
"D": {
"subD_1": "<payload.Field_W.sub_2>",
"subD_2": "<payload.Field_W.sub_4>"
}
}
}
Output
{
"A": "X",
"B": 10,
"C": "Fields or text not mapped to payload",
"D": {
"subD_1": true,
"subD_2": null
}
}
Note: Pls note that hardcoding is not allowed as per the client's request.
Every key-value pair has to be looped.
Based on my understanding of the original question, the following DataWeave script should accomplish the goal. I broke out the work into multiple functions so that it would be easier to follow.
%dw 2.4
output application/json
fun isExpression(value: String): Boolean = ((value startsWith("<")) and (value endsWith(">")))
fun extractExpression(value: String): Any = do {
if (isExpression(value))
dw::core::Strings::unwrap(value, "")
else value
}
fun evaluatePath(context: Object, expression: String): Any = do {
var tokens = expression splitBy "."
---
tokens reduce (val, acc = context) -> acc[val]
}
fun retrieveMappedValue(context: Object, value: String): Any = do {
var retValue = if (isExpression(value))
evaluatePath(context, extractExpression(value))
else value
---
retValue
}
fun remap(context: Object, object: Any, fn): Any = do {
if (object is Object)
entriesOf(object) reduce (val, acc = {}) -> dw::core::Objects::mergeWith(acc, {
(val.key): remap(context, val.value, fn)
})
else fn(context, object)
}
---
remap(payload, payload.mapper, retrieveMappedValue)

Need to retrieve the json key value as null if key not present at the node

{
"a": {
"b": 1,
"c": 0
},
"values": [
{
"d": "WERTY",
"e": "details",
"f": [
{
"addressId": "vvvv",
"address": "ffff"
}
]
},
{
"d": "ZXCVB",
"e": "details"
},
{
"d": "ASDFG",
"e": "details",
"f": [
{
"addressId": "vvvv",
"address": "xxxx"
}
]
}
]
}
After getting the response from restassured, I am trying to fetch the values of a particular key with JsonPath.
I am using:
responseBody.jsonPath().getList("values.f.address)
This is returning me a list - ["ffff","xxxx"]
I want to get - ["ffff",null,"xxxx"]
Is it possible to achieve this with Karate?
JsonPath = values[0].f[0].address
If you are using validatableResonse then you can use:
String res_str = Response.extract().jsonPath().getString("values[0].f[0].address");
The response should be of ValidatableResponse type.
It won't return you null for that absent item, because field address is actually not present in the response body.
You can do it checking whether the f key is available in each object of values array;
If it is available -> add the value of address in each object in f array, to a String list
If it is not available -> add null to the same String list.
I create a org.json.JSONObject from io.restassured.response.Response.
Response response = given()
.when()
.get(url)
.then()
.extract()
.response();
List<String> addressList = new ArrayList<>();
JSONObject responseObject = new org.json.JSONObject(response.body().asString());
JSONArray jsonArray = responseObject.getJSONArray("values");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
if (jsonObject.keySet().contains("f")) {
JSONArray fObjectArray = jsonObject.getJSONArray("f");
for (int j = 0; j < fObjectArray.length(); j++) {
addressList.add(fObjectArray.getJSONObject(j).get("address").toString());
}
} else {
addressList.add(null);
}
}
System.out.println(addressList.toString());
This will print the following result;
[ffff, null, xxxx]

Validate that the values ​of List <String> exist in Json Object and return True or False

I am trying to validate if props:List<String> values ​​exist with message:String and return if the value is true or false.
fun main() {
val message = """
{
"id": "xxxxx",
"action": "Do",
"resource": "Login",
"type": "ok",
"data": {
"username": "+521234567890",
"password": "12345"
}
}"""
val words = listOf("dog","flower","cat")
messageValidator(message,words)}
fun validator(message:String, props:List<String>):Boolean{
val words = props.iterator()
val messagejson = Json.parseJson(message).jsonObject
for(x in words){
//println(x)
//val dataWords = messagejson.containsKey(x)
val dataWords = messagejson.containsKey(x)
//println(dataWords)
if (dataWords == true){
println(x)
return true
}
if (!dataWords){
println(x)
return false
}
}
return false }
I really don't know how to continue validating
Not sure if this is what you were looking for, But this goes over every object in words, And if the message doesn't contain x it returns false, otherwise true.
for(x in words){
if(!messagejson.containsKey(x))
return false
}
return true
}
Instead of using a loop, you could also write:
fun validator(message: String, props: List<String>) =
props.any { message.contains(it) }

Merging a list of maps (of list of string)

Baby Kotlin dev here :)
Considering the following structure:
[
{ "color": ["red", "blue"] },
{ "color": ["red", "green"] },
{ "shape": ["square", "circle"] },
{ "shape": ["rectangle"] }
]
I'd like to obtain the following results where keys and their respective values are merged:
[
{ "color": ["red", "blue", "green"] },
{ "shape": ["square", "circle", "rectangle"] }
]
After some research I was thinking of something like this (doesn't work/compile), but I'm missing some pieces:
val colors1 = mapOf("color" to listOf("red", "blue"))
val colors2 = mapOf("color" to listOf("red", "green"))
val shapes1 = mapOf("color" to listOf("square", "circle"))
val shapes2 = mapOf("color" to listOf("rectangle"))
var mainList = mutableListOf(colors1, colors2, shapes1, shapes2)
mainList.reduce { acc, it -> (acc.asSequence() + it.asSequence())
.distinct()
.groupBy({it.key}, {it.value})
.mapValues { (_, values) -> values.flatten().distinct() }
Any help would be greatly appreciated.
Instead of merging the maps with reduce, you can use flatMap with the map entries. So it should work this way:
mainList
.flatMap { it.entries }
.groupBy({ it.key }, { it.value })
.mapValues { (_, values) -> values.flatten().toSet() }
(runnable sample)
Also, a little bit more efficient way to flatten the values in the last line is:
.mapValues { (_, values) -> values.flatMapTo(mutableSetOf()) { it } }
This removes the overhead of the intermediate collection that was created to store the values between flatten() and distinct()/toSet(), but still ensures that the items are unique because they are added to a mutableSet().
Sample with reassigning the mainList: (link)

get array from inside many objects in kotlin

l am try to build simple app provide flight schedule . the problem is l have many object in json url and the array list inside of these object and l cant to get array list from objects because l got error fatal Caused by: org.json.JSONException: Value
my data json api
{
"result": {
"response": {
"airport": {
"pluginData": {
"schedule": {
"arrivals": {
"data": [
{
"flight": {
"identification": {
"id": null,
"row": 4832637003,
"number": {
"default": "ZP4801",
"alternative": null
},
"callsign": null,
"codeshare": null
}
}
}
]
}
}
}
}
}
}
}
my code for getting data json of array list
private fun handleJson (jsonString: String?){
val jsonArray = JSONArray(jsonString)
val list = ArrayList<FlightShdu>()
var x = 0
while (x < jsonArray.length()){
val jsonObject = jsonArray.getJSONObject(x)
list.add(FlightShdu(
jsonObject.getInt("id"),
jsonObject.getString("callsign")
))
x++
}
val adapter = ListAdapte(this#MainActivity,list)
flightShdu_list.adapter = adapter
}
I would normally suggest for a full structure of the JSON via data classes, as this methodology could potentially be expensive to run multiple times over and over... The following highlights a method to dig into the JSON through jsonObjects by name, and then take the final layer of "identification" and populates a data class that is serializable with the resulting object
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.json.JsonDecodingException
import kotlinx.serialization.json.JsonElement
val data =
"""
{
"result": {
"response": {
"airport": {
"pluginData": {
"schedule": {
"arrivals": {
"data": [{
"flight": {
"identification": {
"id": null,
"row": 4832637003,
"number": {
"default": "ZP4801",
"alternative": null
},
"callsign": null,
"codeshare": null
}
}
}]
}
}
}
}
}
}
}
"""
#Serializable
data class FlightIdentification(
val id: Int?,
val row: String,
val number: IdentificationNumber,
val callsign: String?,
val codeshare: String?
) {
#Serializable
data class IdentificationNumber(
val default: String,
val alternative: String?
)
}
val json = Json(JsonConfiguration.Stable)
fun JsonElement?.get(name: String): JsonElement? {
return if (this == null) null
else this.jsonObject[name]
}
fun handleJson(jsonString: String) {
val obj = json.parseJson(jsonString)
val data = obj.get("result").get("response").get("airport").get("pluginData")
.get("schedule").get("arrivals").get("data")
if (data != null) {
val flight = data.jsonArray[0]
.get("flight").get("identification")
try {
val res = json.parse(FlightIdentification.serializer(), flight.toString())
println(res)
} catch (e: JsonDecodingException) {
println("Decode: ${e.message}")
}
}
}
handleJson(data)