繁体   English   中英

如何对 jsonObject 的值求和并在 JAVA 中的 jsonArray 中创建 sum 的新 jsonobject?

[英]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 字符串,那么这里有另一种方法来实现您想要的内容,方法是使用JacksonLambda Expression (自 Java 8 起)执行以下步骤:

第1步
创建POJO和使用@JsonAnySetter序列化clientclient2List<ClientInfo> ,和使用@JsonIgnoregetName()为反序列化忽略字段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.

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