Despite you can easily accomplish this in imperative manner with/out recursion, it might be easier to implement in functional style. I'm not sure if I'm good at idiomatic functional code in Java 8, but you'd need:
- A collector to collect items to a single array
static Collector<Object, JSONArray, JSONArray> toJSONArray() {
return Collector.of(
JSONArray::new, // Create a new array
JSONArray::add, // Add each element to the target array
(a1, a2) -> { // Merge the second array into the first one
a1.addAll(a2);
return a1;
},
identity() // Return the populated array itself
);
}
- A recursive flatten method (inspired by Recursive use of Stream.flatMap()). Not sure whether it can be implemented easier (
Q43481457
is just the current class name).
static Stream<?> flatten(final Object value) {
return value instanceof Collection
? ((Collection<?>) value).stream().flatMap(Q43481457::flatten) // Flatten recursively
: Stream.of(value); // Otherwise wrap a single element into a stream
}
@SupressWarnings("unchecked")
final Collection<JSON> jsonArray = (Collection<JSON>) originalJsonArray;
final JSONArray flatJSONArray = jsonArray.stream()
.map(json -> (Map<?, ?>) json) // All outer array elements are JSON objects and maps in particular
.map(jsonObject -> jsonObject.values() // Recursively flatten the JSON object values
.stream()
.flatMap(Q43481457::flatten)
.collect(toJSONArray()) // ... collecting them to JSON arrays
)
.collect(toJSONArray()); // ... which are collected to JSON arrays
System.out.println(flatJSONArray);
Output:
[[12,"Whatever",1,2],[34,"Again",23,43]]