0

I'm new to Java I have an array like below

[{'roleName': "driver", "name": "Hub"},{'roleName': "hoc", "name": "Org"},{'roleName': "hubManager", "name": "Hub"}]

I have to format the same into below structure

 {
    Org :{
        role : ["hoc"]
    }
    Hub: {
        role :
            ["driver","hubManager"]
        }
 }

Please help me how we can do this with Java streams

I have tried the below

List<String> roles = roleLevels
                .stream()
                .map(c -> c.getRoleName()).collect(Collectors.toList());

But that's not the expected result

3
  • 1
    Edit your question to include your attempt as well Commented May 24, 2021 at 6:46
  • Unclear both input and output data structures. Post minimal and complete sample. Commented May 24, 2021 at 8:14
  • Inferring the output type to be Map<String, List<String>>, you can make use of Nirmal's answer with a Collectors.mapping downstream added to it. Commented May 24, 2021 at 8:42

4 Answers 4

1

Use groupingBy with downstream Collector:


Map<String, List<String>> result = 
    roleLevels.stream()
              .collect(Collectors.groupingBy(RoleManager::getName, 
                                             Collectors.mapping(RoleManager::getRole,
                                                                Collectors.toList())));
Sign up to request clarification or add additional context in comments.

Comments

0

See if below one helps

roleLevels.stream().collect(Collectors.groupingBy(r -> r.getName()));

1 Comment

you would need to additionally perform a downstream Collectors.mapping within the grouping.
0

See if this helps.

public class ConverToJSON {
public static void main(String[] args) {
    System.out.println(getList());

    final Map<String, Map<String, List<String>>> map = new HashMap<>();

    getList().forEach(roleManager -> getRoleNameList(map, roleManager));
    System.out.println(new JSONObject(map));
}

private static void getRoleNameList(Map<String, Map<String, List<String>>> map, RoleManager roleManager) {
    map.computeIfAbsent(roleManager.getName(), r -> new HashMap<>())
            .computeIfAbsent("role", rn -> new ArrayList<>())
            .add(roleManager.getRole());
}

private static List<RoleManager> getList(){
    List<RoleManager> roles = new ArrayList();
    roles.add(new RoleManager("driver", "Hub"));
    roles.add(new RoleManager("hoc", "org"));
    roles.add(new RoleManager("hubManager", "Hub"));

    return roles;
}

private static class RoleManager {
    final String role;
    final String name;
    public RoleManager(String role, String name) {
        this.role = role;
        this.name = name;
    }

    public String getRole() {
        return role;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "RoleManager{" +
                "driver='" + role + '\'' +
                ", hub='" + name + '\'' +
                '}';
    }
}

}

Below is the expected result:

{
   "Hub":{
      "role":[
         "driver",
         "hubManager"
      ]
   },
   "org":{
      "role":[
         "hoc"
      ]
   }
}

Comments

0

You have received great answers, but in case the exact specified JSON output is needed, there's another thing we need to do.

Let's first create RoleLevel class:

@Getter
public class RoleLevel {
    String roleName;
    String name;
}

Then we can group by name:

ObjectMapper mapper = new ObjectMapper();
String jsonStr = "[{\"roleName\": \"driver\", \"name\": \"Hub\"},{\"roleName\": \"hoc\", \"name\": \"Org\"},{\"roleName\": \"hubManager\", \"name\": \"Hub\"}]";
    List<RoleLevel> roleLevels = mapper.readValue(jsonStr, new TypeReference<List<RoleLevel>>(){});

Map<String, List<String>> nameToRoles = roleLevels.stream()
        .collect(Collectors.groupingBy(RoleLevel::getName, Collectors.mapping(RoleLevel::getRoleName, Collectors.toList())));

System.out.println(mapper.writeValueAsString(nameToRoles));

But the output JSON is not exactly the expected JSON output:

{
    "Hub": ["driver", "hubManager"], // no "role" field
    "Org": ["hoc"]                   // no "role" field
}

To fix this we need to create a Person class:

@AllArgsConstructor
@Getter
@Setter
public class Person {
    List<String> role;
}

then do:

Map<String, Person> personToRoles = nameToRoles.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey, entry -> new Person(entry.getValue())));

System.out.println(mapper.writeValueAsString(personToRoles));

Output:

{
    "Hub": {
        "role": ["driver", "hubManager"]
    },
    "Org": {
        "role": ["hoc"]
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.