Java Stream representation of extracting data from jsonobj - java

I have a service that returns me a response that has the below object
{
"features": [
{
"name": "climateControl"
},
{
"name": "drivingControl"
},
{
"name": "breakeControl",
"type": [
{
"name": "safety"
}
]
},
{
"name": "seatAdjustments",
"type": [
{
"name": "motion"
}
]
},
{
"name": "enginePower",
"type": [
{
"name": "motion"
}
]
}
]
}
Now I need to extract the feature names that are either null or doesn't have any type with name "safety"
I can write something like below
List<Features> features = service.getFeatures();
List<String> refinedList = new ArrayList<>();
for(Feature feature:features){
if(feature.getType==null || feature.getType().getName().equalsIgnoreCase("safety") )
{
refinedList.add(feature.getName());
}
}
Looking for a way to do the same using java streams.

You can use filter for the if conditions and map to getName, then collect as:
List<String> refinedList = features.stream()
.filter(feature -> feature.getType == null || feature.getType().getName().equalsIgnoreCase("safety"))
.map(feature -> feature.getName())
.collect(Collectors.toList());

Related

Jolt nested array transformation

I'm a beginner in jolt transformations and I'm having below input payload that needs to be transformed before sending out
i want to create separate node based on nested array values and insert it back into array and remove the nested array completely from the output
{
"Def": {
"capacity": {
"accounttype": {
"value": "customer"
},
"customer": {
"name": "abc"
},
"config": [
{
"restriction": {
"value": "inbound"
},
"serviceConfig": [
{
"serviceType": {
"value": "standard"
}
},
{
"serviceType": {
"value": "special"
}
}
]
}
]
}
}
}
and expected output is below
{
"Def": {
"capacity": {
"accounttype": {
"value": "customer"
},
"customer": {
"name": "abc"
},
"config": [
{
"restriction": {
"value": "inbound"
},
"serviceType": {
"value": "standard"
}
},
{
"restriction": {
"value": "inbound"
},
"serviceType": {
"value": "special"
}
}
]
}
}
}
I did try multiple things but none of them seems to work,
You can use a shift transformation spec in which walk through the indexes of serviceConfig array and then tile the other elements by using "*": "&2.&1.&" (as else case) such as
[
{
"operation": "shift",
"spec": {
"Def": {
"capacity": {
"*": "&2.&1.&", // &2 stands for going the tree 2 levels up and grabbing the value "Def", &1 for "capacity", & as leaf node which copies the current node's value
"config": {
"*": {
"serviceConfig": {
"*": {
"#(2,restriction)": "&6.&5.&4[&1].restriction",
"*": "&6.&5.&4[&1].&" // &6 -> "Def", &5 -> "capacity", &4 -> "config", [&1] -> indexes of serviceConfig, & -> leaf node which copies the current node's value
}
}
}
}
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

How to handle JsonObject to own Object

Now i take JsonObject from API like this:
Its XML object converted to JsonObject.
"Details": {
"row": [
{
"item": [
{
"name": "Account",
"value": 12521512
},
{
"name": "ACCNO",
"value": 4214
},
{
"name": "Number",
"value": 5436
}
]
},
"item": [
{
"name": "Account",
"value": 5789678
},
{
"name": "ACCNO",
"value": 6654
},
{
"name": "Number",
"value": 0675
}
]
},
But i need convert this object and send like this:
{
"Details": {
"row": [
{
"Account": 12521512,
"ACCNO": 4214,
"Number": 12412421
},
{
"Account": 5789678,
"ACCNO": 6654,
"Number": "0675"
}
]
}
}
I have rows more than 1000, i need faster way to handle.
How to handle, please help me
You could use the JSON-java library to parse your input and transform it to your desired format. Something like this works but you may need to adjust it to your needs:
JSONObject jsonObject = new JSONObject(json); // Load your json here
JSONObject result = new JSONObject("{\"Details\": {\"row\": []}}");
for (Object row : jsonObject.getJSONObject("Details").getJSONArray("row")) {
if (!(row instanceof JSONObject)) continue;
Map<Object, Object> values = new HashMap<>();
for (Object item : ((JSONObject) row).getJSONArray("item")) {
if (!(item instanceof JSONObject)) continue;
values.put(((JSONObject) item).get("name"), ((JSONObject) item).get("value"));
}
result.getJSONObject("Details").getJSONArray("row").put(values);
}
// Now result is in your format

Differences between lists of items and list of items

I was thinking about API path like .../lists/items?listId=1,2,3 to get a response like below.
// Map<Integer, List>
{
1: [
{
"field": "item1"
},
{
"field": "item11"
}
],
2: [
{
"field": "item2"
},
{
"field": "item22"
}
],
3: [
{
"field": "item3"
},
{
"field": "item33"
}
]
}
or
// List<Object>
{
[
{
"field": "item1"
},
{
"field": "item11"
},
{
"field": "item2"
},
{
"field": "item22"
},
{
"field": "item3"
}
{
"field": "item33"
},
]
}
But at the same time, I thought that the api path could be used to express to get following payload.
// List<List<Object>>
{
[
{
"field": "item1"
},
{
"field": "item11"
}
],
[
{
"field": "item2"
},
{
"field": "item22"
}
],
[
{
"field": "item3"
},
{
"field": "item33"
}
]
}
Is there correct answer for three cases above to write REST API path? If not, it would be appreciate to share your experience. Thanks.
I'd use the first method.
The second is the worst, since you have to divide again the lists clientside, which is useless. JSON can send them separately
The third could be used, but you would have to recreate the connection id/list, since lists don't have a key.
The map method maintains the connection id/list and separate all the lists

REST-assured | How to get a string value based on matching critera using JSONpath

I need to get count value based on matching critera using REST Assured Jsonpath
I tried the following but its not working :
response().jsonPath().getString("{it.B == '456'}.B1.size()")
JSON :
[{ "A": "123", "A1": [{ "A11": "A111" }, { "A12": "A112" }, { "A13": "A113" }] },
{ "B": "456", "A1": [{ "B11": "B111" }, { "B12": "B112" }, { "B13": "B113" }, { "B14": "B114" }, { "B15": "B115" }] },
{ "C": "456", "A1": [{ "C11": "C111" }, { "C12": "C112" }, { "C13": "C113" }, { "C14": "C114" }, { "C15": "C115" }, { "C16": "C116" }] }
]
Please try the below, it will return 456
response().jsonPath().getString("$.[1].B")

How to make a JSON Parser to parse elasticsearch mapping in java?

I wanted to parse this structure which is an elasticsearch filter:
{
"filter": {
"name_synonyms_filter": {
"synonym_path": "sample.txt",
"type": "abc_synonym_filter"
},
"name_formatter": {
"name": "name_formatter",
"type": "abc_token_filter"
}
}
}
My question is how can I access individual filters without using key ("name_synonyms_filter" , etc) in java?
your JSON was impropertly formatted.
Here it is fixed:
{
"abc": [{
"name": "somename"
},
{
"name": "somename"
}
]
}
How to parse it:
let x = JSON.parse({
"abc": [{
"name": "somename"
},
{
"name": "somename"
}
]
});
console.log(x);
Let me know if you have any questions.

Categories