简体   繁体   中英

Add a value into two nested JSON array with Lambda, Stream java

I'm a bit new in Lambda and streams. After a lot of researches, I couldn't find the proper answer to my problem. But if you know any related answer, please give me the link, and I will delete this question. Thanks.

My problem is I try to convert the following code into Lambda. But because I use indexes and validation into a nested loop, I couldn't be able to turn it in just one block code with Lambda (is it possible?). Also, I would be grateful if anyone has a suggestion for writing this code in a better way).

for (int i = 0; i < list1.length(); i++) {
    if (list1.getJSONObject(i).has("owner")) {
        dataObject1 = list1.getJSONObject(i).getJSONObject("owner");
        if (GeneralUtils.isNameExist(inputNameOrSubject, dataObject1, true)) {
            if (usersList != null) {
                for (int j = 0; j < usersList.length(); j++) {
                    if (
                            GeneralUtils.isNameExist(usersList.getJSONObject(j).getString("first_name"), dataObject1, false) ||
                                    GeneralUtils.isNameExist(usersList.getJSONObject(j).getString("last_name"), dataObject1, false)
                    ) {
                        usersExist = true;
                        usersIndex = j;
                    }
                }
                if (usersExist) {
                    if (list1.getJSONObject(i).has("name")) {
                        topicName = list1.getJSONObject(i).getString("name");
                        topicListJA = usersList.getJSONObject(usersIndex).getJSONArray("topics");
                        topicExist = false;
                        for (int t = 0; t < topicListJA.length(); t++) {
                            if (topicName.toLowerCase().equals(topicListJA.getString(t).toLowerCase())) {
                                topicExist = true;
                                break;
                            }
                        }
                        if (!topicExist) {
                            usersList.getJSONObject(usersIndex).getJSONArray("topics").put(topicName);
                        }
                    }

                } else {
                    result = dataObject1;
                    result.put("topics", new JSONArray(new String[]{list1.getJSONObject(i).getString("name")}));
                    usersList.put(result);
                }
            } else if (list1.getJSONObject(i).has("name")) {
                result = dataObject1; 
                result.put("topics", new JSONArray(new String[]{list1.getJSONObject(i).getString("name")}));
                usersList = new JSONArray();
                usersList.put(result);
            }

        }

    }
}
return String.valueOf(usersList);

Update: The input list is a JSON array with something like this:

[{
    owner: { 
          signature: "",
          created: "2019-08-26 02:14:15", 
          nickname: "",
          last_name: "Kennedy", 
          title: null,
          first_name: "Victor", 
          updated: "2019-11-24 20:58:57",
          email: "v.kennedy@gmail.com"
    },
     topics: [ 
          {
               id:"0"
               name: "topic 1"
          },{
               id:"1"
               name: "topic 2"
          },{
               id:"0"
               name: "topic 3"
          },
     ]
},

{    owner: {
          signature: "",
          created: "2014-03-25 23:51:48",
          nickname: "",
          last_name: "Kent", 
          title: "",
          first_name: "Bill", 
          updated: "2019-11-21 21:26:24",
          email: "bill.kent@gmail.com"
     },
     topics: [ 
          {
               id:"0"
               name: "topic 6"
          },{
               id:"1"
               name: "topic 7"
          },{
               id:"0"
               name: "topic 8"
          },
     ]
} ,
{
     owner: {
          signature: "",
          created: "2014-03-25 23:51:48",
          nickname: "",
          last_name: "Novel", 
          title: "",
          first_name: "Tim", 
          updated: "2019-10-21 21:26:24",
          email: "tim.novel@gmail.com"
     }
     ,
      topics: [ 
          {
               id:"0"
               name: "topic 16"
          },{
               id:"1"
               name: "topic 17"
          },{
               id:"0"
               name: "topic 18"
          },
     ]
 },
{    owner: {
          signature: "",
          created: "2014-03-25 23:51:48",
          nickname: "",
          last_name: "Kent", 
          title: "",
          first_name: "Bill", 
          updated: "2019-11-21 21:26:24",
          email: "bill.kent@gmail.com"
     },
     topics: [ 
          {
               id:"0"
               name: "topic 36"
          },{
               id:"1"
               name: "topic 37"
          },{
               id:"0"
               name: "topic 38"
          },
     ]
}  
]

And when the API receives the keyword "ken" as a name, I need to send back the first two JSON objects and last one with combined details for topics value (I mean one JSON object for Bill Kent and combined topic: 6,7,8,36,37,38) as a response!

I have to mention it first, your JSON string is not valid. Because you all the keys must be wrapped by double quotes and all the JSON nodes belong to the same JSON array must be separated by comma.

Following code snippet shows another way to achieve what you want. First use a Map with first_name and last_name concatenated by & as key, then combine topics of JSON node whose key is identical. Finally convert the Map to a new JSON node. BTW, Jackson (one of the most popular JSON libraries) is introduced to demo this.

Code snippet

 ObjectMapper mapper = new ObjectMapper();
 ArrayNode root = (ArrayNode) mapper.readTree(jsonStr);
 Map<String, JsonNode> rootMap = new HashMap<>();
 root.forEach(e -> {
     String firstName = e.get("owner").get("first_name").toString().toLowerCase();
     String lastName = e.get("owner").get("last_name").toString().toLowerCase();
     if (firstName.contains("ken") || lastName.contains("ken")) {
         String key = String.format("%s&%s", firstName, lastName);
         if (rootMap.containsKey(key)) {
             e.get("topics").forEach(e1 -> {
                 ((ArrayNode) rootMap.get(key).get("topics")).add(e1);
             });
         } else {
             rootMap.put(key, e);
         }
     }
 });

 ArrayNode rootNew = mapper.createArrayNode();
 rootMap.forEach((k,v) -> {
     rootNew.add(v);
 });
 System.out.println(rootNew.toString());

Console output

[ 
  { 
    "owner":{ 
      "signature":"",
      "created":"2014-03-25 23:51:48",
      "nickname":"",
      "last_name":"Kent",
      "title":"",
      "first_name":"Bill",
      "updated":"2019-11-21 21:26:24",
      "email":"bill.kent@gmail.com"
    },
    "topics":[ 
      { 
        "id":"0",
        "name":"topic 6"
      },
      { 
        "id":"1",
        "name":"topic 7"
      },
      { 
        "id":"0",
        "name":"topic 8"
      },
      { 
        "id":"0",
        "name":"topic 36"
      },
      { 
        "id":"1",
        "name":"topic 37"
      },
      { 
        "id":"0",
        "name":"topic 38"
      }
    ]
  },
  { 
    "owner":{ 
      "signature":"",
      "created":"2019-08-26 02:14:15",
      "nickname":"",
      "last_name":"Kennedy",
      "title":"null",
      "first_name":"Victor",
      "updated":"2019-11-24 20:58:57",
      "email":"v.kennedy@gmail.com"
    },
    "topics":[ 
      { 
        "id":"0",
        "name":"topic 1"
      },
      { 
        "id":"1",
        "name":"topic 2"
      },
      { 
        "id":"0",
        "name":"topic 3"
      }
    ]
  }
]

UPDATE

Here you are! You can get the same result by using org.json as below:

JSONArray root = new JSONArray(jsonStr);
Map<String, JSONObject> rootMap = new HashMap<>();
for (int i = 0; i < root.length(); i++) {
    JSONObject obj = root.getJSONObject(i);
    String firstName = obj.getJSONObject("owner").getString("first_name").toLowerCase();
    String lastName = obj.getJSONObject("owner").getString("last_name").toLowerCase();
    if (firstName.contains("ken") || lastName.contains("ken")) {
        String key = String.format("%s&%s", firstName, lastName);
        if (rootMap.containsKey(key)) {
            obj.getJSONArray("topics").forEach(e1 -> {
                rootMap.get(key).getJSONArray("topics").put(e1);
            });
        } else {
            rootMap.put(key, obj);
        }
    }
}

JSONArray rootNew = new JSONArray();
rootMap.forEach((k,v) -> {
    rootNew.put(v);
});
System.out.println(rootNew.toString());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM