I'm stuck in splitting an array in a sub array in an object. I have the following:
Input/Output AClass:
{
attribute1: 'value1',
attribute2: 'value2',
// etc.
assets: [
{assetAttribute1: 'value1', // etc.},
{assetAttribute2: 'value2', // etc.}
// etc.
]
}
Stream Input:
inputs = [
{
attribute1: 'value1',
attribute2: 'value2',
assets: [
{assetAttribute1: 'value1', // etc.},
{assetAttribute2: 'value2', // etc.}
// etc.
]
},
]
Expected stream output:
outputs = [
{
attribute1: 'value1', // same as from the input
attribute2: 'value2', // same as from the input
assets: [
{assetAttribute1: 'value1', // etc.} // input asset array index 0
]
},
{
attribute1: 'value1', // same as from the input
attribute2: 'value2', // same as from the input
assets: [
{assetAttribute2: 'value2', // etc.} // // input asset array index 1
]
},
]
Kafka Streams code:
KStream<String, AClass> inputs = //...
KStream<String, AClass> output = inputs.map((key, aclass) -> {
return aclass.getAssets().stream().map(asset -> {
AClass transform = new AClass();
transform = aclass.clone();
transform.setAssets(Arrays.asList(asset));
return new KeyValue<String, AClass>(key, miaTransitAsset);
});
});
As you see this can not work. But I'm now stuck how I could achieve that with the Java Streams. You can ignore the Kafka stream as it basically the same.
It is manageable to do it with one stream however, for readability let mi split this fist:
For simplicity, I created myself a class (hopefully got it right from the JSON description):
class Input {
String attribute1;
String attribute2;
List<Map<String, String>> assets;
public Input(String attribute1, String attribute2, List<Map<String, String>> assets) {
this.attribute1 = attribute1;
this.attribute2 = attribute2;
this.assets = assets;
}
}
Then some dumb initialization to have some data to work on:
List<Map<String, String>> assets = new ArrayList<>();
Map<String, String> attributeMap1 = new HashMap<>();
Map<String, String> attributeMap2 = new HashMap<>();
attributeMap1.put("assetAttribute1", "value1");
attributeMap2.put("assetAttribute2", "value2");
assets.add(attributeMap1);
assets.add(attributeMap2);
Input input = new Input("value1", "value2", assets);
List<Input> inputs = Arrays.asList(input);
And here come the lambdas:
First, you have to get all the attributes you want to extract (list of assets over which you will create new objects):
List<Map<String, String>> extractedAssets = inputs
.stream()
.map(e -> e.assets)
.flatMap(Collection::stream)
.collect(Collectors.toList());
Then for each of these assets, you need a copy of what you had in input previously, but with the difference of "assets" list content. So the best way is to create a new object for each previously extractedAsset:
List<Input> collect = extractedAssets.stream()
.map(e -> new Input(
input.attribute1,
input.attribute2,
Collections.singletonList(e)))
.collect(Collectors.toList());
This should work :)
Or with one stream:
List<Input> collect1 = inputs.
stream()
.map(e -> e.assets)
.flatMap(Collection::stream)
.map(e -> new Input(
inputs.get(0).attribute1,
inputs.get(0).attribute2,
Collections.singletonList(e)))
.collect(Collectors.toList());