Reputation: 792
I have a JSON object that looks like this:
[
{
"startAt": 1617605301292,
"endAt": 1617605317095,
"duration": 15803,
"selection": {
"selected.Speed": "0",
"selected.Low": "65535",
"selected.Fast": "7173",
"selected.medium": "5"
},
"details": {
"phase": [{
"value": "2",
"timestamp": 1617605301316
}]
}
},
{
"startAt": 1617603849697,
"endAt": 1617603966378,
"duration": 116681,
"selection": {
"selected.Speed": "0",
"selected.Low": "65535",
"selected.Fast": "123",
"selected.medium": "5"
},
"details": {
"phase": [{
"value": "2",
"timestamp": 1617603849749
}]
}
}
]
I need to count how many times selected.Fast
has occurred. I am trying with stream and this is what I have written so far:
List<Map<String, Object>> jsonObj = mapper.readValue(jArr, new TypeReference<List<Map<String, Object>>>(){});
Map<String, Long> counted = jsonObj.stream()
.map(x -> x.get("selection").toString() )
.collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted.toString());
But I am getting count of all the key inside selection object, and I want count for specific JSON key which is selected.Fast
.
For example:
selected.Fast:"7173" -> occurred 5 times
selected.Fast:"123" -> occurred 2 times
Any help would be appreciated.
Upvotes: 0
Views: 744
Reputation: 11
To output information about a field of the specified name in all levels of JSON records that have indefinite number of levels, the Java code will be long and complicated.
You can use SPL, the open-source Java package, to do this. It is easy and only one line of code is enough:
A | |
---|---|
1 | =json(file("data.json").read()).groups(#4.#3;count(~)).("selected.Fast:\""/#1/""-> occurred -"/#2/"times") |
SPL offers JDBC driver to be invoked by Java. Just store the above SPL script as count.splx and invoke it in Java as you call a stored procedure:
…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st = con.prepareCall("call count()");
st.execute();
…
Upvotes: 0
Reputation: 807
Can you check if this is what you are looking for ?
List<JsonNode> jsonObj = mapper.readValue(jArr, new TypeReference<List<JsonNode>>() {
});
Map<String, Long> counted = jsonObj.stream()
.map(x -> {
String selection = x.get("selection").get("selected.Fast").asText();
return "selected.Fast:" + selection;
}).collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted); //{selected.Fast:123=1, selected.Fast:7173=1}
Edit: Without converting to JsonNode
List<Map<String, Object>> jsonObj = mapper.readValue(jArr, new TypeReference<List<Map<String, Object>>>(){});
Map<String, Long> counted = jsonObj.stream()
.map(x -> {
String selection = ((Map<String,Object>)x.get("selection")).get("selected.Fast").toString();
return "selected.Fast:" + selection;
}).collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted);
Edit 2: Solution to get count of all the elements inside the selection
Map<String, Long> counted = jsonObj.stream().flatMap(x -> {
JsonNode selection = x.get("selection");
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(selection.fields(), 0), false);
})
.map(x -> x.getKey() + ":" + x.getValue()).collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted);
Upvotes: 1
Reputation: 2860
You can use normally deserialize by jackson library and create object structure like that:
@Setter
@Getter
@NoArgsConstructor
static class Source {
private long startAt;
private long endAt;
private long duration;
private SourceSelection selection;
private SourceDetails details;
}
@Setter
@Getter
@NoArgsConstructor
static class SourceSelection {
private long speed;
private long low;
private long fast;
private long medium;
}
@Setter
@Getter
@NoArgsConstructor
static class SourceDetails {
private List<SourcePhase> phase;
}
@Setter
@Getter
@NoArgsConstructor
static class SourcePhase {
private int value;
private long timestamp;
}
And then you need to deserialize your json to Source.class object:
List<Source> sourceList = new ObjectMapper().readValue(
JSON,
new ObjectMapper().getTypeFactory().constructCollectionType(List.class, Source.class)
);
When JSON
is your source json
And then you can use a standart stream API for mapping, filtering, and counting:
long result = sourceList.stream()
.map(Source::getSelection)
.filter(s-> s.getFast() != 0)
.count();
Upvotes: 0
Reputation: 9408
I need to count how many times selected.Fast has occurred.
Is this what you're after?
List<Map<String, Object>> jsonObj = mapper.readValue(jArr, new TypeReference<List<Map<String, Object>>>(){});
long count = jsonObj.stream()
.map(x -> x.get("selection").toString())
.filter(s -> s.contains("selected.Fast"))
.count()
System.out.println(count);
Upvotes: 2