![](/img/trans.png)
[英]How to create JsonArray and JsonObject in JsonObject java
[英]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"
}
]
}
我想对 jsonarray 中每个 jsonobject 的成员值求和并创建额外的 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库( googles json 解析器)的完整示例。
首先,我创建了用于定义初始 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 个不同的对象(一个具有成员和组字段,另一个具有成员和组字段),我们必须做一些层次结构的事情。
如果我们创建一个包含公共字段(组)的父类:
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 和一个新类:
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;
}
}
扩展这个父类,我们可以有一个包含两者的 ClientDataParentSer 列表,即输出 json 文件需要的列表。
新对象的类如下所示:
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这里
您预期的 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()
为反序列化忽略字段name
。
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]]]
第四步
将rootPojo
转换为Map<String, List<ClientInfo>
然后将其反序列化以输出 JSON 字符串:
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,"组":"所有"}]}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.