My json file is like this
{
"Parent1": {
"Child1":"TRUE",
"RandomKey":"TEST-111"
},
"Parent2": {
"Child1":"TRUE",
"AnotherRandomKey":"TEST-432"
}
}
My goal is to extract first occurrence of Child1 from either Parent1 or Parent2 depending on whatever exists, if both exists it should just get the first.
I have the following code written in java but it is always returning false. Not sure what i am doing wrong
final var content = Jackson.getObjectMapper().readTree(//json link);
Stream.concat(
Optional.ofNullable(content.at("/Parent1/Child1")).stream(),
Optional.ofNullable(content.at("/Parent2/Child1")).stream())
.map(JsonNode::asBoolean)
.filter(Objects::nonNull)
.findFirst()
.orElse(false);
I am trying to combine both streams and just find the first occurence of Child1 and return the boolean.
CodePudding user response:
The problem is that for some reason, JsonNode.asBoolean()
is implemented to be case-sensitive. Hence, parses "TRUE"
as false
.
Method that will try to convert value of this node to a Java boolean. JSON booleans map naturally; integer numbers other than
0
map to true, and0
maps tofalse
andStrings
"true"
and"false"
map to corresponding values.
It's not very intuitive because standard JDK wrapper type Boolean
performs parsing in the case-insensitive manner.
As a workaround, we can extract a String
from a node, and then apply Boolean.parseBoolean
.
Note: there's no need to create an Optional
in order to generate a stream. In this case, Optional.ofNullable(content.at())
is an abuse of optional (for more details on the usage of optional see).
We can use Stream.of()
for that purpose.
public static void main(String[] args) throws JsonProcessingException {
String message = """
{
"Parent1": {
"Child1":"TRUE",
"RandomKey":"TEST-111"
},
"Parent2": {
"Child1":"TRUE",
"AnotherRandomKey":"TEST-432"
}
}""";
ObjectMapper mapper = new ObjectMapper();
JsonNode content = mapper.readTree(message);
boolean result = Stream.of(content.at("/Parent1/Child1"), content.at("/Parent2/Child1"))
.filter(Objects::nonNull)
.map(JsonNode::asText)
.map(Boolean::parseBoolean)
.filter(value -> value) // guarding against the case when node "Parent1" doesn't exist
.findFirst()
.orElse(false);
System.out.println(result);
}
Output:
true