Ошибка при чтении json из файла PDF с использованием iText - PullRequest
1 голос
/ 06 февраля 2020

Я пытался прочитать JSON из файла PDF. Я могу записать строку JSON в pdf, но когда я читаю pdf, я получаю сообщение об ошибке, как показано ниже.

Причина: com.google.gson.stream.MalformedJsonException: неопределенный объект в строке 60 столбца 3 путь $ .All_Routes [0] .route_data

Я напечатал JSON перед записью в файл и проверил его в Интернете, используя JSON валидатор, и он действителен JSON но после того, как я напишу в pdf, он станет недействительным . Я только что скопировал JSON из pdf и проверил его онлайн, но он не был проверен и выдает ошибки.

Вот код для записи 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();
}

Кто-нибудь может предложить мне возможные решения для устранения проблемы?

Спасибо

1 Ответ

1 голос
/ 06 февраля 2020

Сравнивая входные данные json с выходными данными, становится ясно, что вы не можете точно извлечь json из PDF-файлов, сгенерированных вашим текущим кодом.

Проблемы возникают, когда рендеринг строки в PDF добавляет разрывы строк, чтобы текст не попал на поля. Каждый разрыв строки в результате, возможно, уже был во входной строке или был введен iText, и в общем случае это невозможно распознать.

Если iText прервал строку в пробеле или пунктуация (двоеточие, запятая, скобка) за пределами имени или значения, эти дополнительные разрывы строк не меняют смысла объекта json, но разрывы строк внутри имен и значений - это отдельная история.

Даже если бы мы могли предположить, что в именах или значениях нет разрывов строк (фактически в значениях в json, которые вы разделяли, есть разрывы строк в значениях, но эти разрывы строк могли закрасться из-за как вы поделились), и, следовательно, мы могли бы просто удалить их, некоторые из этих разрывов строк были применены там, где в исходном значении был пробел, а другие нет. Там, где в пробеле строка разбита, этот пробел отбрасывается и больше не появляется в конечном выводе. И опять же, в общем случае это невозможно распознать, что имеет место только с извлеченным выводом.

Таким образом, точное извлечение невозможно.


Как следствие, у вас есть изменить способ встраивания json в PDF. Поскольку вы не упомянули, почему вы делаете это вообще, и какие альтернативные варианты у вас есть, я не могу дать окончательное предложение, просто представлю некоторые варианты, которые могут или не могут быть совместимы с вашими требованиями:

  • Встроить json не как обычный, stati c контент страницы, а как значение текстового поля многострочной формы. Значения в полях формы могут быть точно извлечены из PDF.
  • В дополнение к видимому json в содержимом страницы, также вставьте json в объект частного потока в PDF; затем вы можете точно извлечь json из этого объекта потока.
  • Используйте размер шрифта настолько мал, что iText не добавляет разрывов строк во время рендеринга. (Однако, скорее всего, результат будет слишком мал для чтения без увеличения.)
  • Визуализируйте json вручную (используя низкоуровневые API-интерфейсы iText) и каким-то образом отметьте добавленные разрывы строк и пропущенные пробелы. Во время извлечения вы должны реагировать на эти маркеры.

Например, чтобы реализовать опцию 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();

( Извлечение Json тест testJsonToPdfToJsonFormField)

Я использую текущую ветку разработки iText 5.5.14-SNAPSHOT. Код должен работать с любой версией 5.5.x.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...