【问题标题】:Error while reading json from pdf file using iText使用 iText 从 pdf 文件读取 json 时出错
【发布时间】:2020-02-06 06:43:00
【问题描述】:

我一直在尝试从 pdf 文件中读取 JSON。我可以将 JSON 字符串写入 pdf,但是当我阅读 pdf 时,我收到如下错误。

原因:com.google.gson.stream.MalformedJsonException:未终止 对象位于第 60 行第 3 列路径 $.All_Routes[0].route_data

我在写入文件之前打印了 JSON,并使用 JSON 验证器在线验证它,它是有效的 JSON,但在我写入到 pdf 之后,它变成了 无效。我只是从 pdf 复制 JSON 并在线验证它,但它没有经过验证并给出错误。

这是将 JSON 写入 pdf 文件的代码。

try {
    File file = AppUtils.createFile(".pdf");
    Document document = new Document();
    document.setPageSize(PageSize.A4);
    document.addCreationDate();
    document.addAuthor("Me");
    PdfWriter.getInstance(document, new FileOutputStream(file));
    document.open();

    String jsonBody = new Gson().toJson(backUpModel);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    JsonParser parser = new JsonParser();
    JsonElement jsonElement = parser.parse(jsonBody);
    String prettyJsonBody = gson.toJson(jsonElement);

    Log.i(Constants.TAG, "Input Json: " + prettyJsonBody);
    document.add(new Paragraph(prettyJsonBody));
    document.close();

    //Toast.makeText(BackUp.this, "Saved Succesfully", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
    e.printStackTrace();
}

这是读取 PDF 文件的代码。

try {
    File exportDir = new File(Environment.getExternalStorageDirectory(), Constants.TAG);
    String filePath = exportDir.getPath() + File.separator + getFileName(fileUri);
    PdfReader pdfReader = new PdfReader(filePath);
    int numberOfPages = pdfReader.getNumberOfPages();
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 1; i <= numberOfPages; i++) {
        stringBuilder.append(PdfTextExtractor.getTextFromPage(pdfReader, i));
    }
    pdfReader.close();
    String jsonBody = stringBuilder.toString();
    BackUpModel backUpModel = new Gson().fromJson(jsonBody, BackUpModel.class);
} catch (IOException e) {
    e.printStackTrace();
}

谁能建议我解决这个问题的可能解决方案?

谢谢

【问题讨论】:

  • “我一直在尝试从 pdf 文件中读取 JSON” - 你是如何尝试的?当您将读取的文本与原始 json 进行比较时,它们有何不同?
  • @mkl 您可以从上述链接中获取 JSON。您可以使用jsonformatter.curiousconcept.com 对其进行验证或比较
  • @mkl 我添加了从 PDF 文件读取 JSON 的代码。
  • 您的问题是new Paragraph(): 添加的换行符和额外空间。 new Paragraph() 是一种抽象,可以自行处理空间、段落等内容。您需要手动执行此操作才能写出完美的JSON
  • 这么说,可能在原始json包含空格的地方出现了一些换行,而这些空格在整个过程中可能会丢失。因此,我的问题是替代方法是否也可以工作......

标签: android json itext gson


【解决方案1】:

比较输入 json 和输出很明显,您无法忠实地从当前代码生成的 PDF 中提取 json。

在将字符串呈现为 PDF 时会出现问题,该问题会添加换行符以防止文本进入页边距。结果中的每个换行符可能已经在输入字符串中,也可能已经被 iText 引入,一般情况下是无法识别的。

如果 iText 在名称或值之外的空格或标点符号(冒号、逗号、括号) 处换行,这些额外的换行符不会改变 json 对象的含义,但行内部名称和值的中断是另一回事。

即使我们可以假设名称或值中没有任何换行符(实际上您共享的 json 中的值中存在换行符,但由于您共享它的方式,这些换行符可能已经潜入),因此,我们可以简单地删除它们,其中一些换行符已应用在原始值中有空格的地方,而另一些则没有。如果在空格处断线,则该空格将被删除并且不再出现在最终输出中。再说一次,一般来说,手头只有提取的输出是无法识别的。

因此,无法进行忠实的提取。


因此,您必须更改在 PDF 中嵌入 json 的方式。由于您根本没有提及您为什么这样做以及您有哪些替代选择,因此我无法给出最终建议,仅提供一些可能与您的要求兼容或不兼容的选项:

  • 嵌入 json 不是作为常规的静态页面内容,而是作为多行表单文本字段的值。可以忠实地从 PDF 中提取表单字段中的值。
  • 除了页面内容中可见的json外,还可以将json嵌入到PDF中的私有流对象中;然后,您可以忠实地从该流对象中提取 json。
  • 使用小字体,以便 iText 在渲染期间不会添加换行符。 (不过,如果不放大,结果很可能太小,无法阅读。)
  • 手动渲染 json(使用低级 iText API)并以某种方式标记您添加的换行符和删除的空格。在提取过程中,您必须对这些标记做出反应。

例如,要实现选项 1,将 json 作为多行表单文本字段的值嵌入,只需像这样添加它:

Document document = new Document();
document.setPageSize(PageSize.A4);
document.addCreationDate();
document.addAuthor("Me");
PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(jsonPdfFile));
document.open();
pdfWriter.getAcroForm().setNeedAppearances(true);
TextField textField = new TextField(pdfWriter, document.getPageSize(), "json");
textField.setOptions(TextField.MULTILINE | TextField.READ_ONLY);
PdfFormField field = textField.getTextField();
field.setValueAsString(originalJson);
pdfWriter.addAnnotation(field);
document.close();

然后像这样再次提取它:

PdfReader pdfReader = new PdfReader(jsonPdfFile.getAbsolutePath());
String jsonBody = pdfReader.getAcroFields().getField("json");
pdfReader.close();

(ExtractJson 测试testJsonToPdfToJsonFormField)

我正在使用当前的 iText 5.5.14-SNAPSHOT 开发分支。不过,该代码应该适用于任何 5.5.x 版本。

【讨论】:

  • 你能解释一下我该怎么做吗?嵌入 json 不是作为常规的静态页面内容,而是作为多行表单文本字段的值。可以忠实地从 PDF 中提取表单字段中的值。
  • "你能解释一下吗..." - 我在答案中添加了一个示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-27
  • 1970-01-01
相关资源
最近更新 更多