繁体   English   中英

将数组的 JSON 数组转换为特定类的 Java 列表

[英]Convert JSON array of arrays to Java List of a specific class

假设我有从以下格式的源中提取的 JSON 数据:

{
  "fileName" : "C:\\Users\\jgagnon\\sample_data\\PDM_BOM.xlsx",
  "sheets" : [ {
    "name" : "PDM_BOM",
    "data" : [ [ "BRANCH", "PARENT ITEM NUMBER", "2ND ITEM NUMBER", "QUANTITY REQUIRED", "UNIT OF MEASURE", "ISSUE TYPE CODE", "LINE TYPE", "STOCK TYPE", "TYPE BOM", "LINE NUMBER", "OPERATING SEQUENCE", "EFFECTIVE FROM DATE", "EFFECTIVE THRU DATE", "DRAWING NUMBER", "UNIT COST", "SCRAP PERCENT" ],
        [ "B20", "208E8840040", "5P884LPFSR2", 0.32031, "LB", "I", "S", "M", "M", 1.0, 10.0, "09/11/13", "12/31/40", null, 0.0, 0.0 ],
        [ "B20", "208E8840168", "5P884LPFSR2", 1.36, "LB", "I", "S", "M", "M", 1.0, 10.0, "02/26/08", "12/31/40", null, 0.0, 0.0 ],
        [ "B20", "208E8840172", "5P884LPFSR2", 1.3924, "LB", "I", "S", "M", "M", 1.0, 10.0, "02/26/08", "12/31/40", null, 0.0, 0.0 ],
        [ "B20", "208E8840180", "5P884LPFSR2", 1.4565, "LB", "I", "S", "P", "M", 1.0, 10.0, "03/04/09", "12/31/40", null, 0.0, 0.0 ],
        [ "B20", "21PPH150166", "8P315TPMRG", 1.39629, "LB", "I", "S", "M", "M", 1.0, 10.0, "03/05/18", "12/31/40", null, 0.0, 0.0 ] ],
    "maxCols" : 16,
    "maxRows" : 14996
  } ]
}

我关心的信息在data元素中,它是一个数组数组,表示工作表中的行。 第一行包含列标题。

现在,假设我有一个 Java 类BOM.java ,如下所示:

public class BOM {

  private String branch;
  private String parentItemNumber;
  private String secondItemNumber;
  private double quantityRequired;
  private String unitOfMeasure;
  private String issueTypeCode;
  private String lineType;
  private String stockType;
  private String typeBom;
  private double lineNumber;
  private double operatingSequence;
  private String effectiveFromDate;
  private String effectiveThruDate;
  private String drawingNumber;
  private double unitCost;
  private double scrapPercent;

  // getters/setters omitted
}

有没有办法解析这个 JSON 数据,结果是一个java.util.ListBOM对象?

我至少假设我需要在上面的类中添加一些 Jackson “JSON” 注释以帮助 Jackson 进行字段映射?

到目前为止,我已经使用 Jackson ObjectMapper.readTree(File)方法来提取数据。 这提供了一个JsonNode层次结构,我可以导航到项目。

我发现了一些提到使用 Jackson TypeFactoryTypeReference ,但我不明白它们是如何工作的,也无法让它们为我工作。

这是我目前使用的简单程序:

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JSONObjectReader {

  public static void main(String[] args)
      throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();
    JsonNode root = mapper.readTree(new File("PDM_BOM.json"));
    JsonNode sheets = root.get("sheets");
    JsonNode sheet1 = sheets.get(0);
    JsonNode dataNode = sheet1.get("data");

    // skip first row
    for (int i = 1; i < dataNode.size(); i++) {
      JsonNode n = dataNode.get(i);
      System.out.println(n);
    }
  }

}

您的列表结构几乎就像一个 CSV:一行列名,后跟多行值。 环顾四周,我找不到任何 Jackson 内置函数来处理这样的结构——甚至没有一个在忽略第一个元素的情况下解析列表。

我认为您应该忽略第一个元素的原因是,如果您的目标是解析为 POJO而不是例如Map<String, String> ,将很难处理。 这是因为如果第一行不固定,您的字段名称可能会更改,然后您的 POJO 将不再反映您正在解析的内容。 最好忽略标头,或者如果它与您期望的不匹配则抛出异常,并专注于解析后续数组。

我这样做的方法是编写一个自定义反序列化器,用于将List<List<String>>转换为List<BOM> 解串器应该:

  1. 获取列表的原始列表
  2. 抛出(或验证)第一个条目
  3. 对于所有后续条目,将它们转换为BOM
    1. 我会通过编写一个接受List<String>BOM构造函数来做到这一点,但您也可以在反序列化器中完成所有转换。

应该有效:

List<DTO> result = new ArrayList<>();

for (int i = 1; i < dataNode.size(); i++) {
  JsonNode n = dataNode.get(i);
  result.add(mapper.readValue(mapper.writeValueAsString(n), DTO.class));
}
 

请注意,它真的很丑 - 它解析所有节点,然后在最终重新解析为 DTO 之前写回 JSON 字符串。 更干净的版本需要处理格式错误的第一行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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