Я сталкиваюсь с трудностями в сценарии, когда мне нужно прочитать объект JSON на Java, который не имеет двойных кавычек в ключах и значений, как в примере ниже:
"{id: 267107086801, productCode: 02-671070868, lastUpdate: 2018-07-15, lastUpdateTimestamp: 2018-07-15 01:49:58, user: {pf: {document: 123456789, name: Luis Fernando}, address: {street: Rua Pref. Josu00e9 Alves Lima,number:37}, payment: [{sequential: 1, id: CREDIT_CARD, value: 188, installments: 9}]}"
Я смог добавить двойные кавычки в поля, используя код ниже, с replaceAll и библиотекой Гсон:
String jsonString = gson.toJson (obj);
String jsonString = jsonString.replaceAll ("([\\ w] +) [] *:", "\" $ 1 \ ":"); // to quote before: value
jsonString = jsonString.replaceAll (": [] * ([\\ w @ \\.] +)", ": \" $ 1 \ ""); // to quote after: value, add special character as needed to the exclusion list in regex
jsonString = jsonString.replaceAll (": [] * \" ([\\ d] +) \ "", ": $ 1"); // to un-quote decimal value
jsonString = jsonString.replaceAll ("\" true \ "", "true"); // to un-quote boolean
jsonString = jsonString.replaceAll ("\" false \ "", "false"); // to un-quote boolean
Однако поля с датами разбиваются ошибочно, например:
"{"id" : 267107086801,"productCode" : 02-671070868,"lastUpdate" : 2018-07-15,"lastUpdateTimestamp" : 2018-07-15 "01" : 49 : 58,"user" :{"pf":{"document" : 123456789, "name" : "Luis" Fernando},"address" :{"street" : "Rua"Pref.Josu00e9AlvesLima,"number" : 37},"payment" : [{"sequential" : 1,"id" : "CREDIT_CARD","value" : 188,"installments" : 9}]}"
Кроме того, строки с пробелами также неверны. Как я мог исправить эту логику? Что я делаю неправильно? Заранее спасибо.
Это недействительный JSON, вам нужно это исправить.
@P.J.Meisch, спасибо! На самом деле, мое приложение не создает этот json. Мы получаем csv-файл с этой информацией в поле, и, к сожалению, исправить ее не удается. Мне нужно преобразовать эту строку в допустимый JSON.
«Фальшивый json» сломан несколькими способами, вы заметили Rua Pref. Josu00e9 Alves Lima? Вам также нужно будет найти последовательности u[0-9a-fA-F]{4} и преобразовать их в символ с его значением Unicode.




String incorrectJson = "{id: 267107086801, productCode: 02-671070868,"
+ " lastUpdate: 2018-07-15, lastUpdateTimestamp: 2018-07-15 01:49:58,"
+ " user: {pf: {document: 123456789, name: Luis Fernando},"
+ " address: {street: Rua Pref. Josu00e9 Alves Lima,number:37},"
+ " payment: [{sequential: 1, id: CREDIT_CARD, value: 188, installments: 9}]}";
String correctJson = incorrectJson.replaceAll("(?<=: ?)(?![ \\{\\[])(.+?)(?=,|})", "\"$1\"");
System.out.println(correctJson);
Вывод:
{id: "267107086801", productCode: "02-671070868", lastUpdate: "2018-07-15", lastUpdateTimestamp: "2018-07-15 01:49:58", user: {pf: {document: "123456789", name: "Luis Fernando"}, address: {street: "Rua Pref. Josu00e9 Alves Lima",number:"37"}, payment: [{sequential: "1", id: "CREDIT_CARD", value: "188", installments: "9"}]}
Одним из недостатков нетривиальных регулярных выражений является то, что их трудно читать. Тот, который я использую здесь, соответствует каждому буквальному значению (но не значениям, которые являются объектами или массивами). Я использую двоеточия, запятые и фигурные скобки для сопоставления, поэтому мне не нужно заботиться о том, что находится внутри каждого строкового значения, это могут быть любые символы (кроме запятой или правой фигурной скобки). Части означают:
(?<=: ?): перед значением стоит двоеточие и, возможно, пробел (lookbehind)(?![ \\{\\[]) значение нет начинается с пробела, фигурной скобки или квадратной скобки (отрицательный просмотр вперед; пусто, потому что мы не хотим, чтобы пробел между двоеточием и значением воспринимался как часть значения)(.+?): значение состоит как минимум из одного символа, как можно меньше (неохотный квантификатор, иначе регулярное выражение попытается взять оставшуюся часть строки)(?=,|}): после значения стоит либо запятая, либо правая фигурная скобка (положительный просмотр вперед).Не разбираясь в JSON, я не думаю, что вам нужно цитировать имя. Однако вы можете:
String correctJson = incorrectJson.replaceAll(
"(?<=\\{|, ?)([a-zA-Z]+?): ?(?![ \\{\\[])(.+?)(?=,|})", "\"$1\": \"$2\"");
{"id": "267107086801", "productCode": "02-671070868", "lastUpdate": "2018-07-15", "lastUpdateTimestamp": "2018-07-15 01:49:58", user: {pf: {"document": "123456789", "name": "Luis Fernando"}, address: {"street": "Rua Pref. Josu00e9 Alves Lima","number": "37"}, payment: [{"sequential": "1", "id": "CREDIT_CARD", "value": "188", "installments": "9"}]}
Я сделал несколько тестов, адаптировав свое решение к этому подходу, который вы предложили, и он отлично работал. Большое тебе спасибо!
строка, которую вы пытаетесь проанализировать как JSON, не является допустимым JSON. От куда это? Вы должны исправить место, где создается эта строка, чтобы она создавала правильный JSON.