如何对 jsonObject 的值求和并在 JAVA 的 jsonArray 中创建新的 jsonObject of sum?
How to sum values of jsonObject and create new jsonobject of sum inside a jsonArray in JAVA?
我有如下所示的 JSON 数组,想要对 JSON 对象的值求和并在 JSON 数组中创建新的 JSON 求和对象:
{
"client":[
{
"member":12,
"group":"g1"
},
{
"member":17,
"group":"g2"
}
],
"client2":[
{
"member":14,
"group":"g11"
},
{
"member":175,
"group":"g22"
}
]
}
我想对 json 数组中每个 json 对象的成员值求和并创建额外的 json 并将其放入客户端数组中。预期的 json 应如下所示:
{
"client":[
{
"member":12,
"group":"g1"
},
{
"member":17,
"group":"g2"
},
{
"totalMember":29,
"group":"all"
}
],
"client2":[
{
"member":14,
"group":"g11"
},
{
"member":175,
"group":"g22"
},
{
"totalMember":189,
"group":"all"
}
]
}
我试过:
mainJson.fieldNames().forEach(fn->{
JsonArray jsonArray = mainJson.getJsonArray(fn);
int id = 0;
for (int i = 0; i < jsonArray.size(); i++) {
id += jsonArray.getJsonObject(i).getInteger("id");
JsonObject jsonObject = new JsonObject().put("id",id).put("group","all");
jsonArray.add(jsonObject);
mainJson.put(fn,jsonArray);
}
});
因此,下面是一个使用 gson 库(谷歌 json 解析器)的完整示例。
首先我创建了 class 用于定义初始 json 文件:
import java.io.Serializable;
import java.util.ArrayList;
public class ClientSer implements Serializable {
ArrayList<ClientDataSer> client;
ArrayList<ClientDataSer> client2;
public ClientSer(ArrayList<ClientDataSer> client, ArrayList<ClientDataSer> client2) {
this.client = client;
this.client2 = client2;
}
public ArrayList<ClientDataSer> getClient() {
return client;
}
public void setClient(ArrayList<ClientDataSer> client) {
this.client = client;
}
public ArrayList<ClientDataSer> getClient2() {
return client2;
}
public void setClient2(ArrayList<ClientDataSer> client2) {
this.client2 = client2;
}
}
客户端数据服务看起来像:
public class ClientDataSer extends ClientDataParentSer {
int member;
public ClientDataSer(int member, String group) {
super(group);
this.member = member;
}
public int getMember() {
return member;
}
public void setMember(int member) {
this.member = member;
}
}
为了让 gson 使用文件作为数据结构的定义,它们需要是可序列化的。稍后我将了解 ClientDataSer 扩展 ClientDataParentSer 的原因。
读取该文件,计算成员总值并打印到另一个文件的代码如下所示:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.*;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
try (Reader reader = new FileReader("test.json")) {
// Convert JSON File to Java Object
ClientSer clientSer = gson.fromJson(reader, ClientSer.class);
ClientNewSer clientNewSer = new ClientNewSer(getNewClientData(clientSer.getClient()), getNewClientData(clientSer.getClient2()));
try {
Writer writer = new FileWriter("testNew.json");
gson.toJson(clientNewSer, writer);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static ArrayList<ClientDataParentSer> getNewClientData(ArrayList<ClientDataSer> clientDataSerList) {
ArrayList<ClientDataParentSer> clientDataSers = new ArrayList<>();
int memberCounter = 0;
for (ClientDataParentSer clientDataSer : clientDataSerList) {
clientDataSers.add(clientDataSer);
memberCounter += ((ClientDataSer)clientDataSer).getMember();
}
ClientDataNewSer clientDataNewSer = new ClientDataNewSer("all", memberCounter);
clientDataSers.add(clientDataNewSer);
return clientDataSers;
}
}
因此,由于您希望 client 和 client2 包含一个列表,每个列表包含 2 个不同的对象(一个包含字段 member 和 group,另一个包含字段 total member 和 group),我们必须做一些层次结构的事情。
如果我们创建包含公共字段(组)的父项 class:
import java.io.Serializable;
public class ClientDataParentSer implements Serializable {
private final String group;
public ClientDataParentSer(String group) {
this.group = group;
}
public String getGroup() {
return group;
}
}
然后创建 ClientDataSer 和一个新的 class:
public class ClientDataNewSer extends ClientDataParentSer {
int member;
public ClientDataNewSer(String group, int member) {
super(group);
this.member = member;
}
public int getMember() {
return member;
}
public void setMember(int member) {
this.member = member;
}
}
扩展这个父级 class,我们可以得到一个包含两者的 ClientDataParentSer 列表,即输出 json 文件需要的列表。
新对象的 class 如下所示:
import java.io.Serializable;
import java.util.ArrayList;
public class ClientNewSer implements Serializable {
ArrayList<ClientDataParentSer> client;
ArrayList<ClientDataParentSer> client2;
public ClientNewSer(ArrayList<ClientDataParentSer> client, ArrayList<ClientDataParentSer> client2) {
this.client = client;
this.client2 = client2;
}
public ArrayList<ClientDataParentSer> getClient() {
return client;
}
public void setClient(ArrayList<ClientDataParentSer> client) {
this.client = client;
}
public ArrayList<ClientDataParentSer> getClient2() {
return client2;
}
public void setClient2(ArrayList<ClientDataParentSer> client2) {
this.client2 = client2;
}
}
有任何问题请在下方评论。
完整的项目在我的 github here
你期望的 JSON 字符串不正常,因为属于同一个 JSON 数组的任何 JSON 对象应该具有相同的结构,所以输出的 JSON 字符串应该如下所示:
{
"client":[
{
"member":12,
"group":"g1"
},
{
"member":17,
"group":"g2"
},
{
"member":29,
"group":"all"
}
],
...
}
如果您期望的 JSON 字符串可以这样修改,那么这里有另一种方法可以通过 Jackson
和 Lambda Expression
的步骤来实现您想要的(因为 Java 8):
步骤 1
创建POJO并使用@JsonAnySetter
将client
和client2
序列化为List<ClientInfo>
,并使用@JsonIgnore
对getName()
进行反序列化以忽略字段[=23] =].
class RootPojo {
private List<ClientInfo> clients = new ArrayList<>();
@JsonAnySetter
public void setClients(String name, List<ClientInfo> client) {
client.forEach(e -> {
e.setName(name);
});
this.clients.addAll(client);
}
//general getter and toString
}
class ClientInfo {
private String name;
private int member;
private String group;
@JsonIgnore
public String getName() {
return name;
}
//general getters, setters and toString
}
步骤 2
使用 Jackson
:
将 JSON 字符串序列化为预定义的 POJO
ObjectMapper mapper = new ObjectMapper();
RootPojo rootPojo = mapper.readValue(inputJsonStr, RootPojo.class);
System.out.println(rootPojo.toString());
控制台输出:
RootPojo [clients=[ClientInfo [name=client, member=12, group=g1], ClientInfo [name=client, member=17, group=g2], ClientInfo [name=client2, member=14, group=g11], ClientInfo [name=client2, member=175, group=g22]]]
步骤 3
使用 Lambda Expression
进行分组和求和,这也会将结果作为新的 JSON 对象添加回原始 JSON 字符串。
rootPojo.getClients()
.stream()
.collect(Collectors.groupingBy(ClientInfo::getName,
Collectors.summingInt(ClientInfo::getMember)))
.forEach((k,v) -> {
ClientInfo clientInfo = new ClientInfo();
clientInfo.setName(k);
clientInfo.setGroup("all");
clientInfo.setMember(v);
rootPojo.getClients().add(clientInfo);
});
System.out.println(rootPojo.toString());
控制台输出:
RootPojo [clients=[ClientInfo [name=client, member=12, group=g1], ClientInfo [name=client, member=17, group=g2], ClientInfo [name=client2, member=14, group=g11], ClientInfo [name=client2, member=175, group=g22], ClientInfo [name=client, member=29, group=all], ClientInfo [name=client2, member=189, group=all]]]
步骤 4
将 rootPojo
转换为 Map<String, List<ClientInfo>
然后反序列化输出 JSON string:
Map<String, List<ClientInfo>> clientMap = new HashMap<>();
rootPojo.getClients().forEach(e -> {
if (clientMap.containsKey(e.getName())) {
clientMap.get(e.getName()).add(e);
} else {
List<ClientInfo> clients = new ArrayList<>();
clients.add(e);
clientMap.put(e.getName(), clients);
}
});
String outputJsonStr = mapper.writeValueAsString(clientMap);
System.out.println(outputJsonStr);
控制台输出:
{"client":[{"member":12,"group":"g1"},{"member":17,"group":"g2"},{"member":29,"group":"all"}],"client2":[{"member":14,"group":"g11"},{"member":175,"group":"g22"},{"member":189,"group":"all"}]}
我有如下所示的 JSON 数组,想要对 JSON 对象的值求和并在 JSON 数组中创建新的 JSON 求和对象:
{
"client":[
{
"member":12,
"group":"g1"
},
{
"member":17,
"group":"g2"
}
],
"client2":[
{
"member":14,
"group":"g11"
},
{
"member":175,
"group":"g22"
}
]
}
我想对 json 数组中每个 json 对象的成员值求和并创建额外的 json 并将其放入客户端数组中。预期的 json 应如下所示:
{
"client":[
{
"member":12,
"group":"g1"
},
{
"member":17,
"group":"g2"
},
{
"totalMember":29,
"group":"all"
}
],
"client2":[
{
"member":14,
"group":"g11"
},
{
"member":175,
"group":"g22"
},
{
"totalMember":189,
"group":"all"
}
]
}
我试过:
mainJson.fieldNames().forEach(fn->{
JsonArray jsonArray = mainJson.getJsonArray(fn);
int id = 0;
for (int i = 0; i < jsonArray.size(); i++) {
id += jsonArray.getJsonObject(i).getInteger("id");
JsonObject jsonObject = new JsonObject().put("id",id).put("group","all");
jsonArray.add(jsonObject);
mainJson.put(fn,jsonArray);
}
});
因此,下面是一个使用 gson 库(谷歌 json 解析器)的完整示例。
首先我创建了 class 用于定义初始 json 文件:
import java.io.Serializable;
import java.util.ArrayList;
public class ClientSer implements Serializable {
ArrayList<ClientDataSer> client;
ArrayList<ClientDataSer> client2;
public ClientSer(ArrayList<ClientDataSer> client, ArrayList<ClientDataSer> client2) {
this.client = client;
this.client2 = client2;
}
public ArrayList<ClientDataSer> getClient() {
return client;
}
public void setClient(ArrayList<ClientDataSer> client) {
this.client = client;
}
public ArrayList<ClientDataSer> getClient2() {
return client2;
}
public void setClient2(ArrayList<ClientDataSer> client2) {
this.client2 = client2;
}
}
客户端数据服务看起来像:
public class ClientDataSer extends ClientDataParentSer {
int member;
public ClientDataSer(int member, String group) {
super(group);
this.member = member;
}
public int getMember() {
return member;
}
public void setMember(int member) {
this.member = member;
}
}
为了让 gson 使用文件作为数据结构的定义,它们需要是可序列化的。稍后我将了解 ClientDataSer 扩展 ClientDataParentSer 的原因。
读取该文件,计算成员总值并打印到另一个文件的代码如下所示:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.*;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
try (Reader reader = new FileReader("test.json")) {
// Convert JSON File to Java Object
ClientSer clientSer = gson.fromJson(reader, ClientSer.class);
ClientNewSer clientNewSer = new ClientNewSer(getNewClientData(clientSer.getClient()), getNewClientData(clientSer.getClient2()));
try {
Writer writer = new FileWriter("testNew.json");
gson.toJson(clientNewSer, writer);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static ArrayList<ClientDataParentSer> getNewClientData(ArrayList<ClientDataSer> clientDataSerList) {
ArrayList<ClientDataParentSer> clientDataSers = new ArrayList<>();
int memberCounter = 0;
for (ClientDataParentSer clientDataSer : clientDataSerList) {
clientDataSers.add(clientDataSer);
memberCounter += ((ClientDataSer)clientDataSer).getMember();
}
ClientDataNewSer clientDataNewSer = new ClientDataNewSer("all", memberCounter);
clientDataSers.add(clientDataNewSer);
return clientDataSers;
}
}
因此,由于您希望 client 和 client2 包含一个列表,每个列表包含 2 个不同的对象(一个包含字段 member 和 group,另一个包含字段 total member 和 group),我们必须做一些层次结构的事情。
如果我们创建包含公共字段(组)的父项 class:
import java.io.Serializable;
public class ClientDataParentSer implements Serializable {
private final String group;
public ClientDataParentSer(String group) {
this.group = group;
}
public String getGroup() {
return group;
}
}
然后创建 ClientDataSer 和一个新的 class:
public class ClientDataNewSer extends ClientDataParentSer {
int member;
public ClientDataNewSer(String group, int member) {
super(group);
this.member = member;
}
public int getMember() {
return member;
}
public void setMember(int member) {
this.member = member;
}
}
扩展这个父级 class,我们可以得到一个包含两者的 ClientDataParentSer 列表,即输出 json 文件需要的列表。
新对象的 class 如下所示:
import java.io.Serializable;
import java.util.ArrayList;
public class ClientNewSer implements Serializable {
ArrayList<ClientDataParentSer> client;
ArrayList<ClientDataParentSer> client2;
public ClientNewSer(ArrayList<ClientDataParentSer> client, ArrayList<ClientDataParentSer> client2) {
this.client = client;
this.client2 = client2;
}
public ArrayList<ClientDataParentSer> getClient() {
return client;
}
public void setClient(ArrayList<ClientDataParentSer> client) {
this.client = client;
}
public ArrayList<ClientDataParentSer> getClient2() {
return client2;
}
public void setClient2(ArrayList<ClientDataParentSer> client2) {
this.client2 = client2;
}
}
有任何问题请在下方评论。
完整的项目在我的 github here
你期望的 JSON 字符串不正常,因为属于同一个 JSON 数组的任何 JSON 对象应该具有相同的结构,所以输出的 JSON 字符串应该如下所示:
{
"client":[
{
"member":12,
"group":"g1"
},
{
"member":17,
"group":"g2"
},
{
"member":29,
"group":"all"
}
],
...
}
如果您期望的 JSON 字符串可以这样修改,那么这里有另一种方法可以通过 Jackson
和 Lambda Expression
的步骤来实现您想要的(因为 Java 8):
步骤 1
创建POJO并使用@JsonAnySetter
将client
和client2
序列化为List<ClientInfo>
,并使用@JsonIgnore
对getName()
进行反序列化以忽略字段[=23] =].
class RootPojo {
private List<ClientInfo> clients = new ArrayList<>();
@JsonAnySetter
public void setClients(String name, List<ClientInfo> client) {
client.forEach(e -> {
e.setName(name);
});
this.clients.addAll(client);
}
//general getter and toString
}
class ClientInfo {
private String name;
private int member;
private String group;
@JsonIgnore
public String getName() {
return name;
}
//general getters, setters and toString
}
步骤 2
使用 Jackson
:
ObjectMapper mapper = new ObjectMapper();
RootPojo rootPojo = mapper.readValue(inputJsonStr, RootPojo.class);
System.out.println(rootPojo.toString());
控制台输出:
RootPojo [clients=[ClientInfo [name=client, member=12, group=g1], ClientInfo [name=client, member=17, group=g2], ClientInfo [name=client2, member=14, group=g11], ClientInfo [name=client2, member=175, group=g22]]]
步骤 3
使用 Lambda Expression
进行分组和求和,这也会将结果作为新的 JSON 对象添加回原始 JSON 字符串。
rootPojo.getClients()
.stream()
.collect(Collectors.groupingBy(ClientInfo::getName,
Collectors.summingInt(ClientInfo::getMember)))
.forEach((k,v) -> {
ClientInfo clientInfo = new ClientInfo();
clientInfo.setName(k);
clientInfo.setGroup("all");
clientInfo.setMember(v);
rootPojo.getClients().add(clientInfo);
});
System.out.println(rootPojo.toString());
控制台输出:
RootPojo [clients=[ClientInfo [name=client, member=12, group=g1], ClientInfo [name=client, member=17, group=g2], ClientInfo [name=client2, member=14, group=g11], ClientInfo [name=client2, member=175, group=g22], ClientInfo [name=client, member=29, group=all], ClientInfo [name=client2, member=189, group=all]]]
步骤 4
将 rootPojo
转换为 Map<String, List<ClientInfo>
然后反序列化输出 JSON string:
Map<String, List<ClientInfo>> clientMap = new HashMap<>();
rootPojo.getClients().forEach(e -> {
if (clientMap.containsKey(e.getName())) {
clientMap.get(e.getName()).add(e);
} else {
List<ClientInfo> clients = new ArrayList<>();
clients.add(e);
clientMap.put(e.getName(), clients);
}
});
String outputJsonStr = mapper.writeValueAsString(clientMap);
System.out.println(outputJsonStr);
控制台输出:
{"client":[{"member":12,"group":"g1"},{"member":17,"group":"g2"},{"member":29,"group":"all"}],"client2":[{"member":14,"group":"g11"},{"member":175,"group":"g22"},{"member":189,"group":"all"}]}