Заменить & на & amp; используя Jackson ObjectMapper
В приложении, с которым я работаю, у нас есть требование преобразовать огромный JSON в еще больший XML. Структура обоих элементов очень различна, поэтому мы решили создать файл XML, соответствующий XSD, и заполнить поля с использованием языка унифицированных выражений. Например:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Objects xmlns="..">
<Object>
<Field>${json.field}</Field>
<Object>
<Objects>
Замена ${json.field}
делается с помощью JUEL
После запуска процесса JUEL мы демонтируем строку xml в объект и продолжаем процесс. Демонстрационный код выглядит примерно так:
private XmlObjects unmarshal(StringReader xmlString) {
try {
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (XmlObjects) unmarshaller.unmarshal(xmlString);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
Проблема, с которой мы сталкиваемся, заключается в том, что json.field
может содержать символы, которые не разрешены в XML, например & или <,>.
Простое решение - заменить все & by & en описанным выше методом, но это не решит проблему <или>, и я не могу заменить это в этой точке.
То, что я хотел бы сделать, это использовать Джексона, чтобы сделать замену, когда json отображается в POJO, но я не могу найти способ сделать это. До сих пор я пытался создать кастом CharacterEscapes
класс и установка, что к ObjectMapper
но не сработало.
Итак, это тест, который суммирует все:
@Test
public void test() throws IOException {
ObjectMapper objectMapper = Jackson.newObjectMapper();
objectMapper.getFactory().setCharacterEscapes(new XMLCharacterEscapes());
String json = "{\"variable\":\"a string with &\"}";
FooJson fooJson = objectMapper.readValue(json, FooJson.class);
assertEquals("a string with &", fooJson.getVariable());
}
Это XMLCharacterEscapes
учебный класс:
public class XMLCharacterEscapes extends CharacterEscapes {
private final int[] asciiEscapes;
public XMLCharacterEscapes() {
int[] esc = CharacterEscapes.standardAsciiEscapesForJSON();
esc['&'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes = esc;
}
@Override
public int[] getEscapeCodesForAscii() {
return asciiEscapes;
}
@Override
public SerializableString getEscapeSequence(int i) {
return new SerializedString("&");
}
}
2 ответа
Поместите свое поле в раздел CDATA
<Field><![CDATA[${json.field}]]></Field>
Если я могу предложить альтернативу, можете ли вы вместо этого сделать так, чтобы ваш unmarshaller применил JUEL к значениям элемента при чтении XML? Или вы можете пройтись по графу объектов XML после демаршаллинга и применить JUEL к значениям элемента?
Изменить: Кажется, что проблема заключается только в порядке применения замен. Получив XML-документ, вы сможете установить любые значения, которые вам нравятся, и он позаботится о правильном экранировании.