Home > other >  How to flatten nested json to map with entity using Java 8 Stream?
How to flatten nested json to map with entity using Java 8 Stream?

Time:10-10

I have a structure that looks like this for RechargeResponse Model:

public class RechargeResponse {
    private String code;
    private String status;
    private Set<OperatorWiseCircles> payload; 
   // setter and getters
}

here is the OperatorWiseCircles Model

public class OperatorWiseCircles {
    private String operatorName;
    private String operatorId;
    private List<CircleWisePlan> circleWisePlanLists;
//setter and getters
}

CircleWisePlan Model class

public class CircleWisePlan {
    private String circleName;
    private String circleId;
}

Below is the sample json which we need to flattern.

{
  "code": 200,
  "status": "SUCCESS",
  "payload": [
    {
      "operatorName": "VODAFONE",
      "operatorId": "VF",
      "circleWisePlanLists": [
        {
          "circleName": "C1",
          "circleId": "1"
        },
        {
          "circleName": "C2",
          "circleId": "2"
        }
      ]
    }
  ]
}

I am expecting this to be flattern and map it to Entity object, so that I can add all these iteration to Hashset and save them all to DB, I want to do it using java8 stream. I how can I do it efficiently. I didnt get the right example, to parse nested json values and create entities for it using map/ flatmap. Result should be like

Eg: ["VODAFONE","VF","C1", "1"]---> ENTRY1 ["VODAFONE","VF","C2", "2"] ---> ENTRY2

@Entity
public class RechargePlanEntity extends Audit<String>{
    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name="operator_name")
    private String operatorName;

    @Column(name="operator_id")
    private String operatorId;

    @Column(name="circle_name")
    private String circleName;

    @Column(name="circle_id")
    private String circleId;       

}

CodePudding user response:

The entities without ids may be created from RechargeResponse model providing that the entity has all-args constructor:

RechargeResponse modelFromJson = ... //

List<RechargePlanEntity> entities = modelFromJson.getPayload()
        .stream() // Stream<OperatorWiseCircles>
        .flatMap(ows -> ows.getCircleWisePlanLists()
                           .stream() // Stream<CircleWisePlan>
                           .map(cwp -> new RechargePlanEntity(
                               null, // instead of id
                               ows.getOperatorName(),
                               ows.getOperatorId(),
                               cwp.getCircleName(),
                               cwp.getCircleId()
                           )) // Stream<RechargePlanEntity>
        ) // Stream<RechargePlanEntity>
        .collect(Collectors.toList());

or, if a builder is implemented in the entity class (e.g. using Lombok's @Builder annotation), this conversion may look as follows:

List<RechargePlanEntity> entities = modelFromJson.getPayload()
        .stream() // Stream<OperatorWiseCircles>
        .flatMap(ows -> ows.getCircleWisePlanLists()
                           .stream() // Stream<CircleWisePlan>
                           .map(cwp -> RechargePlanEntity.builder()
                               .operatorName(ows.getOperatorName())
                               .operatorId(ows.getOperatorId())
                               .circleName(cwp.getCircleName())
                               .circleId(cwp.getCircleId())
                               .build()
                           ) // Stream<RechargePlanEntity>
        ) // Stream<RechargePlanEntity>
        .collect(Collectors.toList());

CodePudding user response:

Truth is I'm sure is there any easy way to do this, Yet you can follow something like this,

Here in this example I have created utility class to map OperatorWiseCircles class to List<RechargePlanEntity>.

public class Main {
    public static void main(String[] args) throws IOException {

        String s = "{\"code\":200,\"status\":\"SUCCESS\",\"payload\":[{\"operatorName\":\"VODAFONE\",\"operatorId\":\"VF\",\"circleWisePlanLists\":[{\"circleName\":\"C1\",\"circleId\":\"1\"},{\"circleName\":\"C2\",\"circleId\":\"2\"}]}]}";

        ObjectMapper om = new ObjectMapper();
        RechargeResponse response = om.readValue(s, RechargeResponse.class);

        List<RechargePlanEntity> collection = response.getPayload()
                .stream()
                .map(MapUtil::toEntity)
                .flatMap(Collection::stream)
                .collect(Collectors.toList());

        System.out.println(collection);
    }
}

@Getter
@Setter
@ToString
class RechargePlanEntity {
    private Long id;
    private String operatorName;
    private String operatorId;
    private String circleName;
    private String circleId;
}

@Getter
@Setter
class RechargeResponse {
    private String code;
    private String status;
    private Set<OperatorWiseCircles> payload;
}

@Getter
@Setter
class OperatorWiseCircles {
    private String operatorName;
    private String operatorId;
    private List<CircleWisePlan> circleWisePlanLists;
}

@Getter
@Setter
class CircleWisePlan {
    private String circleName;
    private String circleId;
}

final class MapUtil {

    public static List<RechargePlanEntity> toEntity(OperatorWiseCircles in) {
        return in.getCircleWisePlanLists()
                .stream()
                .map(MapUtil::map)
                .peek(out -> map(in, out))
                .collect(Collectors.toList());
    }

    private static RechargePlanEntity map(CircleWisePlan in) {
        RechargePlanEntity out = new RechargePlanEntity();
        out.setCircleId(in.getCircleId());
        out.setCircleName(in.getCircleName());
        return out;
    }

    private static void map(OperatorWiseCircles in, RechargePlanEntity out) {
        out.setOperatorId(in.getOperatorId());
        out.setOperatorName(in.getOperatorName());
    }
}
  • Related