大json字符串处理

背景:

当从API获取数据或与其他系统交换信息时。有时json字符串可能会非常庞大,以至于读取到内存中会导致内存溢出或者性能问题

流式处理

如果JSON字符串过大,不适合一次性加载到内存中,可以考虑使用流式处理。例如,使用Jackson库的JsonParser,可以逐行解析JSON,从而避免一次性加载整个字符串。

一般大json中都会存在某个数组中有超多的数据记录,我们需要解决的就是记录当前token路径,在读取到超大json数组时,再利用逐条数据读取mapper.readTree(jsonParser)逐条读取数据,利用数组缓存一定量的数据后,写入数据库后继续读取,直到json数组数据读取结束

ObjectMapper mapper = new ObjectMapper();
JsonParser parser = mapper.getFactory().createParser(jsonStream);

JsonParser进行解析的大致流程如下:

  1. 从头开始扫描JSON字符串
  2. 依次识别每个JSON组成元素
  3. 解析到结束位置,关闭解析器

分块读取

如果从网络或文件中读取JSON,可以使用缓冲区分块读取,而不是一次性读取整个文件。例如,使用Java NIO的BufferedReader。

Path path = Paths.get("large.json");
StringBuilder jsonBuilder = new StringBuilder();
try (BufferedReader reader = Files.newBufferedReader(path)) {
    String line;
    while ((line = reader.readLine()) != null) {
        jsonBuilder.append(line).append("\n");
    }
} catch (IOException e) {
    e.printStackTrace();
}
String jsonString = jsonBuilder.toString();

使用第三方库

有些库如Gson、Jackson提供了直接从输入流中解析JSON的功能,无需将整个JSON字符串加载到内存中。

InputStream inputStream = new FileInputStream("large.json");
Gson gson = new Gson();
YourModel model = gson.fromJson(inputStream, YourModel.class);
inputStream.close();

总结:

处理大型JSON字符串时,要避免一次性加载到内存中,以免造成内存溢出。通过使用StringBuilder、流式处理、分块读取或者借助第三方库,保证性能,又能避免内存问题。

 

背景:

酒店报价接口,会返回大量结构复杂的json数据,当需要追踪返回数据时非常困难,因此需要有清晰json解析方法

方法设计:

public class HotelTest {
  @Test
  public void test() throws IOException {
      //读取resource目录下的.json文件中的几个字段的值
      // 获取资源文件
      ClassLoader classLoader = getClass().getClassLoader();
      InputStream inputStream = classLoader.getResourceAsStream("execption.json");
      // 读取文件内容
      ObjectMapper objectMapper = new ObjectMapper();
      JsonNode jsonNode = objectMapper.readTree(inputStream);
      // 提取所需字段
      JsonNode nestedNode = jsonNode.path("data").path("rooms");
      for (JsonNode room : nestedNode) {
          JsonNode room1 = room.path("rateplans");
          //通过rateplan判断多个rateplan是不是同质化房型
          List<SymRoom> symRooms = new ArrayList<>();
          for (JsonNode rateplan : room1) {
              //room1是第一个房型的所有报价对象,rateplan是其中一个报价对象
              String paymentType = rateplan.get("paymentType").asText();
              String breakfast = rateplan.get("breakfast").asText();
              String status = rateplan.get("status").asText();
              String customerType = rateplan.get("customerType").asText();
              String daysMin = rateplan.get("daysMin").asText();
              Double totalRate = rateplan.get("totalRate").asDouble();
              String refundType = rateplan.get("refundType").asText();
              String refundTime = rateplan.get("refundTime").asText();
              String refundDesc = rateplan.get("refundDesc").asText();
							//组装对象
              SymRoom symRoom = new SymRoom();
              symRoom.setPaymentType(paymentType);
              symRoom.setBreakfast(breakfast);
              symRoom.setStatus(status);
              symRoom.setCustomerType(customerType);
              symRoom.setDaysMin(daysMin);
              symRoom.setTotalRate(totalRate);
              symRoom.setRefundType(refundType);
              symRoom.setRefundTime(refundTime);
              symRoom.setRefundDesc(refundDesc);
              symRooms.add(symRoom);
              // 打印提取的字段值
              System.out.println("paymentType: " + paymentType);
              System.out.println("breakfast: " + breakfast);
              System.out.println("status: " + status);
              System.out.println("customerType: " + customerType);
              System.out.println("daysMin: " + daysMin);
              System.out.println("totalRate: " + totalRate);
              System.out.println("refundType: " + refundType);
              System.out.println("refundTime: " + refundTime);
              System.out.println("refundDesc: " + refundDesc);
              System.out.println("totalRate是否为空:" + Objects.isNull(totalRate));
              System.out.println("====================================");
          }
      }
  }
}

 

posted @ 2024-09-29 14:53  complexlong  阅读(709)  评论(0)    收藏  举报