Znikające znaki \ przed cudzysłowem w Stringu

Wątek przeniesiony 2024-10-28 09:27 z Java przez ŁF.

1

Cześć, posiadam plik JSON z następującymi tekstami, który odczytuję i zapisuję do listy obiektów texts

private final ObjectMapper objectMapper = new ObjectMapper();
List<Text> texts = new ArrayList<>();

try {
    JsonNode rootNode = objectMapper.readTree(new File(filePath));

    Iterator<Map.Entry<String, JsonNode>> fields = rootNode.fields();
    while (fields.hasNext()) {
        Map.Entry<String, JsonNode> field = fields.next();

        String abbr = field.getKey();
        String fullText = field.getValue().asText();
		
		Text text = new Text(abbr, fullText);
		texts.add(text);
	} catch (IOException e) {
        e.printStackTrace();
    }
}

Niestety, gdy chcę te teksty zapisać potem do pliku .sql, to wszystkie teksty które miały w JSONie taki wygląd:

{
	"tzn.": "Oznacza \"To znaczy\"",
	"jw.": "Oznacza \"Jak wyżej\"",
	"dr": "Oznacza \"Doktor\""
}

Wyglądają tak:

INSERT INTO Texts(abbr, full_text) VALUES
	('tzn.', 'Oznacza "To znaczy"'),
	('jw.', 'Oznacza "Jak wyżej"'),
	('dr', 'Oznacza "Doktor"'),

Kod wstawiania:

try (BufferedWriter writer = new BufferedWriter(new FileWriter("file.sql"))) {
	writer.write("INSERT INTO Texts(abbr, full_text) VALUES\n");
	for (Text text : texts) {
		writer.write(String.format("\t('%s', '%s'),", text.getAbbr(), text.getFullText());
	}
}

Już w debuggerze widzę, że Stringi z tej listy texts mają wycięte znaki . Jak obejść te escape`owanie znaku '' ?

1

A jaki jest problem?

6

Wszystko gra.
Cudzysłowy w JSON służą do oznaczania początku i końca klucza i jego wartości, zatem użyte wewnątrz nich muszą być zacytowane. Cytowanie odbywa się poprzez umieszczenie przed cudzysłowem backslasha.
Tę samą właściwość, z tego samego powodu, mają stringi w java. Jednak faktyczna wartość to nie "\"", tylko ", możesz to sprawdzić np. poprzez "\"".length(). Wyjdzie 1.
Tymczasem cudzysłowy w SQL nie służą do niczego, bo używa się tam apostrofów. Z tego powodu w SQL nie tylko nie ma potrzeby cytowania cudzysłowów, ale wręcz byłoby to błędem.

Dlatego kod podany przez Ciebie jest prawidłowy pod tym względem. Ale jeśli w JSON pojawi się apostrof...

1

@zbyniuPDK

Wygladaja tak:

Jak wyżej, a jak mają wyglądać?

3

Problem jest między krzesłem a klawiaturą

screenshot-20241024162914.png

0

Chciałbym, aby wyglądało tak:

INSERT INTO Texts(abbr, full_text) VALUES
	('tzn.', 'Oznacza \"To znaczy\"'),
	('jw.', 'Oznacza \"Jak wyżej\"'),
	('dr', 'Oznacza \"Doktor\"'),

Czyli żeby nie zjadało tych znaków \

1

Ale dlaczego?
Jeżeli chcesz utworzyć string w javie oznaczający
\" to musisz escapować backslash czyli \\"

Pytanie tylko jaki cel za tym stoi?
Bo może wcale nie potrzebujesz zapisywać escapowanych backslashy przy serializacji json.

0

BTW jeśli robisz tabelę z pewnego rodzaju słownikiem i przed każdym rozwinięciem słowa dodajesz "Oznacza ", a samo rozwinięcie zawsze dajesz w cudzysłowach, to chyba coś nie tak zaprojektowałeś.

0
zbyniuPDK napisał(a):

Chciałbym, aby wyglądało tak:

INSERT INTO Texts(abbr, full_text) VALUES
	('tzn.', 'Oznacza \"To znaczy\"'),
	('jw.', 'Oznacza \"Jak wyżej\"'),
	('dr', 'Oznacza \"Doktor\"'),

Czyli żeby nie zjadało tych znaków \

Cześć @zbyniuPDK!

Pytanko 😊 Po co chcesz zachować backslashe? Bo wtedy w bazie będzie również tekst z backslashami. Czy próbujesz to zrobić po to, bo potem gdzieś wyświetlasz ten tekst w miejscu które potrzebuje tych backslashy?

Bo jeśli tak, to w tym miejscu one powinny być dodane - przy wyświetlaniu, nie w bazie.

1

Według mnie to wszystko po kolei jest tutaj skopane, na początek JSON
Powinien przechowywać tablice obiektów coś takiego

[
 {
    “shortcut” : “jw”
    “description” : “Jak wyżej”
 },
 {
    "shortcut" : dr.”
    “description” : “Doktor"
 }
]

Po co chcesz zapisywać do bazy całe zdania które możesz sobie wygenerować jakimś String formatem.

 String.format("%s oznacza: %s", aStringVar, aStringVar2)

Odczyt w przypadku takiego jsona miałbym też easy bo objectMapper serializowałby Ci na liste typu klasy np.

class Entry {

    Long id;
    String shortcut;
    String description;
}

jeszcze oznaczyć ją jako encja JPA i wgl SQLa nie trzeba ruszać.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.